improved file dialogs for mac os x, changed create-executable interface, and fixed parsing of infix dots to require a delimitter after the second dot

svn: r1000
This commit is contained in:
Matthew Flatt 2005-10-06 15:54:38 +00:00
parent 0d44f44db9
commit 5c1a331d3b
10 changed files with 524 additions and 170 deletions

View File

@ -131,10 +131,17 @@ executables.
> (mred-launcher-is-directory?) - Returns #t if MrEd launchers for the
current platform correspond to directories (as on Mac OS X).
current platform are directories from the user's perspective.
> (mzscheme-launcher-is-directory?) - Returns #t if MzScheme launchers
for the current platform correspond to directories.
for the current platform are directories from the user's perspective.
> (mred-launcher-is-actually-directory?) - Returns #t if MrEd
launchers for the current platform are implemented as directories.
> (mzscheme-launcher-is-actually-directory?) - Returns #t if MzScheme
launchers for the current platform are implemented as directories.
> (mred-launcher-add-suffix path) - Returns a path with a suitable
@ -147,10 +154,10 @@ executables.
> (mred-launcher-put-file-extension+style+filters) - Returns three
values suitable for use as the `extension', `style', and `filters'
arguments to `put-file', respectively. If MrEd launchers for this
platform are directories, the `style' result is suitable for use
with `get-directory', and the `extension' result may be a string
indicating a required extension for the directory name (e.g., ".app"
for Mac OS X).
platform are directories from the user perspective, the `style'
result is suitable for use with `get-directory', and the `extension'
result may be a string indicating a required extension for the
directory name (e.g., ".app" for Mac OS X).
> (mzscheme-launcher-put-file-extension+style+filters) - Like
`mred-launcher-get-file-extension+style+filters', but for MzScheme

View File

@ -23,6 +23,9 @@
mred-launcher-is-directory?
mzscheme-launcher-is-directory?
mred-launcher-is-actually-directory?
mzscheme-launcher-is-actually-directory?
mred-launcher-add-suffix
mzscheme-launcher-add-suffix

View File

@ -528,16 +528,21 @@
[else (mred-program-launcher-path name)]))
(define (mred-launcher-is-directory?)
#f)
(define (mzscheme-launcher-is-directory?)
#f)
(define (mred-launcher-is-actually-directory?)
(and (eq? 'macosx (system-type))
(not (memq (current-launcher-variant) '(script script-3m)))))
(define (mzscheme-launcher-is-directory?)
(define (mzscheme-launcher-is-actually-directory?)
#f)
;; Helper:
(define (put-file-extension+style+filters type)
(case type
[(windows) (values ".exe" null '(("Executable" "*.exe")))]
[(macosx) (values ".app" '(enter-packages) #f)]
[(macosx) (values ".app" '(packages) '(("App" "*.app")))]
[else (values #f null null)]))
(define (mred-launcher-add-suffix path)

View File

@ -47,7 +47,6 @@
(check-top-level-parent/false who parent)
(check-path/false who directory) (check-path/false who filename) (check-string/false who extension)
(check-style who #f (cond
[put? null]
[dir? '(enter-packages)]
[else '(packages enter-packages)]) style)
(unless (and (list? filters)

View File

@ -246,6 +246,8 @@
(err/rt-test (readstr "( . 8 9)") exn:fail:read?)
(err/rt-test (readstr "(1 . 2 3 . 4)") exn:fail:read?)
(err/rt-test (readstr "(1 . 2 . 3 . 4)") exn:fail:read?)
(err/rt-test (readstr "(1 . 2 .3)") exn:fail:read?)
(err/rt-test (readstr "(1 . 2 .a)") exn:fail:read?)
(err/rt-test (readstr "#(8 . )") exn:fail:read?)
(err/rt-test (readstr "#( . )") exn:fail:read?)
(err/rt-test (readstr "#( . 8)") exn:fail:read?)
@ -284,6 +286,7 @@
(test '(1 2 3) readstr "(2 . 1 . 3)")
(test '(1 2 3 4) readstr "(2 . 1 . 3 4)")
(test '(1 2 3 4) readstr "(2 3 . 1 . 4)")
(test '(2 . 0.4) readstr "(2 . .4)")
(err/rt-test (readstr "#ha") exn:fail:read:eof?)
(err/rt-test (readstr "#ham") exn:fail:read?)

View File

@ -1,4 +1,11 @@
Version 299.403
Changed label->plain-label to strip parenthesized mneumonics
Added 'package and 'enter-package flags to put-file, and
changed Mac OS X put-file to use extension and filters args
----------------------------------------------------------------------
Version 299.400, September 2005
No MrEd-specific changes

View File

@ -4326,7 +4326,7 @@ static Scheme_Object *expand_path(int argc, Scheme_Object *argv[])
return scheme_make_sized_path(filename, strlen(filename), 1);
}
static Scheme_Object *directory_list(int argc, Scheme_Object *argv[])
static Scheme_Object *do_directory_list(int break_ok, int argc, Scheme_Object *argv[])
{
#if !defined(NO_READDIR) || defined(USE_MAC_FILE_TOOLBOX) || defined(USE_FINDFIRST)
char *filename;
@ -4366,9 +4366,11 @@ static Scheme_Object *directory_list(int argc, Scheme_Object *argv[])
while (1) {
# endif
filename = do_expand_filename(path, NULL, 0,
"directory-list",
break_ok ? "directory-list" : NULL,
NULL, 1, 259 - 4 /* leave room for \*.* in Windows */,
SCHEME_GUARD_FILE_READ);
break_ok ? SCHEME_GUARD_FILE_READ : 0);
if (!filename)
return NULL;
#ifdef USE_FINDFIRST
/* Eliminate "." and "..": */
if (SAME_OBJ(path, argv[0])) {
@ -4383,14 +4385,19 @@ static Scheme_Object *directory_list(int argc, Scheme_Object *argv[])
#endif
} else {
filename = SCHEME_PATH_VAL(CURRENT_WD());
scheme_security_check_file("directory-list", NULL, SCHEME_GUARD_FILE_EXISTS);
scheme_security_check_file("directory-list", filename, SCHEME_GUARD_FILE_READ);
if (break_ok) {
scheme_security_check_file("directory-list", NULL, SCHEME_GUARD_FILE_EXISTS);
scheme_security_check_file("directory-list", filename, SCHEME_GUARD_FILE_READ);
}
}
if (filename && !scheme_directory_exists(filename))
scheme_raise_exn(MZEXN_FAIL_FILESYSTEM,
"directory-list: could not open \"%q\"",
filename);
if (filename && !scheme_directory_exists(filename)) {
if (break_ok)
scheme_raise_exn(MZEXN_FAIL_FILESYSTEM,
"directory-list: could not open \"%q\"",
filename);
return NULL;
}
#endif
#ifdef USE_MAC_FILE_TOOLBOX
@ -4403,9 +4410,11 @@ static Scheme_Object *directory_list(int argc, Scheme_Object *argv[])
raise_null_error("directory-list", argv[0], "");
} else {
filename = SCHEME_PATH_VAL(CURRENT_WD());
scheme_security_check_file("directory-list", NULL, SCHEME_GUARD_FILE_EXISTS);
if (break_ok)
scheme_security_check_file("directory-list", NULL, SCHEME_GUARD_FILE_EXISTS);
}
scheme_security_check_file("directory-list", filename, SCHEME_GUARD_FILE_READ);
if (break_ok)
scheme_security_check_file("directory-list", filename, SCHEME_GUARD_FILE_READ);
if (!find_mac_file(filename, 0, &dir, 1, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0)) {
if (argc) {
@ -4426,7 +4435,7 @@ static Scheme_Object *directory_list(int argc, Scheme_Object *argv[])
find_position++;
if (!(find_position & 0x15)) {
if (break_ok && !(find_position & 0x15)) {
scheme_thread_block(0);
scheme_current_thread->ran_some = 1;
}
@ -4502,7 +4511,7 @@ static Scheme_Object *directory_list(int argc, Scheme_Object *argv[])
last = elem;
}
counter++;
if (!(counter & 0x15)) {
if (break_ok && !(counter & 0x15)) {
BEGIN_ESCAPEABLE(FIND_CLOSE, hfile);
scheme_thread_block(0);
END_ESCAPEABLE();
@ -4540,7 +4549,7 @@ static Scheme_Object *directory_list(int argc, Scheme_Object *argv[])
last = elem;
counter++;
if (!(counter & 0xF)) {
if (break_ok && !(counter & 0xF)) {
BEGIN_ESCAPEABLE(closedir, dir);
scheme_thread_block(0);
END_ESCAPEABLE();
@ -4556,6 +4565,104 @@ static Scheme_Object *directory_list(int argc, Scheme_Object *argv[])
#endif
}
static Scheme_Object *directory_list(int argc, Scheme_Object *argv[])
{
return do_directory_list(1, argc, argv);
}
char *scheme_find_completion(char *fn)
{
int len;
Scheme_Object *p, *l, *a[2], *f, *matches, *fst;
int isdir, max_match;
Scheme_Object *base;
len = strlen(fn);
if (!len)
return NULL;
f = scheme_split_path(fn, len, &base, &isdir);
if (isdir) {
/* Look for single file/prefix in directory: */
base = scheme_make_sized_path(fn, len, 0);
f = scheme_make_sized_path("", 0, 0);
} else {
if (!SCHEME_PATHP(base))
return NULL;
}
a[0] = base;
l = do_directory_list(0, 1, a);
if (!l)
return NULL;
matches = scheme_null;
while (SCHEME_PAIRP(l)) {
p = SCHEME_CAR(l);
if ((SCHEME_PATH_LEN(p) >= SCHEME_PATH_LEN(f))
&& !memcmp(SCHEME_PATH_VAL(f), SCHEME_PATH_VAL(p), SCHEME_PATH_LEN(f))) {
matches = scheme_make_pair(p, matches);
}
l = SCHEME_CDR(l);
}
if (SCHEME_NULLP(matches))
return NULL;
if (SCHEME_NULLP(SCHEME_CDR(matches))) {
/* One match */
a[0] = base;
a[1] = SCHEME_CAR(matches);
p = scheme_build_path(2, a);
a[0] = p;
if (SCHEME_TRUEP(directory_exists(1, a))) {
/* Add trailing separator if one is not there */
fn = SCHEME_PATH_VAL(p);
len = SCHEME_PATH_LEN(p);
if (!IS_A_SEP(fn[len-1])) {
char *naya;
naya = (char *)scheme_malloc_atomic(len + 2);
memcpy(naya, fn, len);
naya[len++] = FN_SEP;
naya[len] = 0;
fn = naya;
}
} else
fn = SCHEME_PATH_VAL(p);
return fn;
}
fst = SCHEME_CAR(matches);
max_match = SCHEME_PATH_LEN(fst);
for (l = SCHEME_CDR(matches); SCHEME_PAIRP(l); l = SCHEME_CDR(l)) {
int i, l2;
p = SCHEME_CAR(l);
l2 = SCHEME_PATH_LEN(p);
if (max_match < l2)
l2 = max_match;
else if (l2 < max_match)
max_match = l2;
for (i = 0; i < l2; i++) {
if (SCHEME_PATH_VAL(fst)[i] != SCHEME_PATH_VAL(p)[i]) {
max_match = i;
break;
}
}
}
if (max_match <= SCHEME_PATH_LEN(f))
/* No longer match available: */
return NULL;
/* Build match */
a[0] = base;
a[1] = scheme_make_sized_path(SCHEME_PATH_VAL(fst), max_match, 0);
f = scheme_build_path(2, a);
return SCHEME_PATH_VAL(f);
}
static Scheme_Object *filesystem_root_list(int argc, Scheme_Object *argv[])
{
Scheme_Object *first = scheme_null;

View File

@ -1950,6 +1950,33 @@ static Scheme_Object *attach_shape_property(Scheme_Object *list,
ReadParams *params,
int closer);
static int next_is_delim(Scheme_Object *port,
ReadParams *params,
int brackets,
int braces)
{
int next;
next = scheme_peekc_special_ok(port);
return ((next == EOF)
|| (next == SCHEME_SPECIAL)
|| (!params->table
&& (scheme_isspace(next)
|| (next == '(')
|| (next == ')')
|| (next == '"')
|| (next == ';')
|| (next == '\'')
|| (next == '`')
|| (next == ',')
|| ((next == '[') && brackets)
|| ((next == '{') && braces)
|| ((next == ']') && brackets)
|| ((next == '}') && braces)))
|| (params->table
&& (readtable_kind(params->table, next, params)
& (READTABLE_WHITESPACE | READTABLE_TERMINATING))));
}
static Scheme_Object *honu_add_module_wrapper(Scheme_Object *list,
Scheme_Object *stxsrc,
Scheme_Object *port);
@ -1964,7 +1991,7 @@ read_list(Scheme_Object *port,
ReadParams *params)
{
Scheme_Object *list = NULL, *last = NULL, *car, *cdr, *pair, *infixed = NULL, *prefetched = NULL;
int ch = 0, next, got_ch_already = 0;
int ch = 0, got_ch_already = 0;
int brackets = params->square_brackets_are_parens;
int braces = params->curly_braces_are_parens;
long start, startcol, startline, dotpos, dotcol, dotline, dot2pos, dot2line, dot2col;
@ -2154,25 +2181,7 @@ read_list(Scheme_Object *port,
} else if (!params->honu_mode
&& params->can_read_dot
&& (ch == '.')
&& (next = scheme_peekc_special_ok(port),
((next == EOF)
|| (next == SCHEME_SPECIAL)
|| (!params->table
&& (scheme_isspace(next)
|| (next == '(')
|| (next == ')')
|| (next == '"')
|| (next == ';')
|| (next == '\'')
|| (next == '`')
|| (next == ',')
|| ((next == '[') && brackets)
|| ((next == '{') && braces)
|| ((next == ']') && brackets)
|| ((next == '}') && braces)))
|| (params->table
&& (readtable_kind(params->table, next, params)
& (READTABLE_WHITESPACE | READTABLE_TERMINATING)))))) {
&& next_is_delim(port, params, brackets, braces)) {
scheme_tell_all(port, &dotline, &dotcol, &dotpos);
track_indentation(indentation, dotline, dotcol);
@ -2186,7 +2195,7 @@ read_list(Scheme_Object *port,
cdr = read_inner(port, stxsrc, ht, indentation, params, 0);
ch = skip_whitespace_comments(port, stxsrc, ht, indentation, params);
if (ch != closer) {
if (ch == '.') {
if ((ch == '.') && next_is_delim(port, params, brackets, braces)) {
/* Parse as infix: */
if (shape == mz_shape_hash_elem) {

View File

@ -244,6 +244,10 @@ int wxMessageBox(char* message, char* caption, long style,
return wxsMessageBox(message, caption, style, parent);
}
//****************************************************************************
// File selector
//****************************************************************************
#ifndef OS_X
extern "C" {
#endif
@ -252,8 +256,11 @@ extern "C" {
#ifndef OS_X
}
#endif
//= T.P. ==============================================================================
extern "C" {
extern char *scheme_expand_filename(char* filename, int ilen, const char *errorin, int *ex, int guards);
extern int scheme_is_complete_path(const char *s, long len);
extern char *scheme_find_completion(char *fn);
}
static int navinited = 0;
@ -275,17 +282,290 @@ static int log_base_10(int i)
class wxCallbackInfo {
public:
NavDialogRef dialog;
int has_parent;
char *initial_directory;
char *force_extension;
};
//-----------------------------------------------------------------------------
// Text path dialog
//-----------------------------------------------------------------------------
/* Cocoa's navigation dialog let's the user type "/" to get a dialog
for entering an aboslute path in text, and tab implements path
completion. Carbon's navigation dialog doesn't do that, so we roll
our own. */
class wxCallbackCallbackInfo {
public:
WindowRef dialog;
ControlRef txt;
NavCBRecPtr callBackParms;
wxCallbackInfo *cbi;
};
static char *extract_string(wxCallbackCallbackInfo *ccbi)
{
int len;
char *result;
CFStringRef str;
Size sz;
::GetControlData(ccbi->txt, kControlEntireControl,
kControlEditTextCFStringTag, sizeof(CFStringRef), &str, &sz);
len = ::CFStringGetLength(str);
result = new WXGC_ATOMIC char[len * 6 + 1];
::CFStringGetCString(str, result, len * 6 + 1, kCFStringEncodingUTF8);
::CFRelease(str);
return result;
}
static OSStatus ok_evt_handler(EventHandlerCallRef inHandlerCallRef,
EventRef inEvent,
void *inUserData)
{
char *result;
FSSpec spec;
wxCallbackCallbackInfo *ccbi = (wxCallbackCallbackInfo *)GET_SAFEREF(inUserData);
WindowRef dialog = ccbi->dialog;
result = extract_string(ccbi);
result = scheme_expand_filename(result, -1, NULL, NULL, 0);
if (result && scheme_mac_path_to_spec(result, &spec)) {
AEDesc desc;
NavCBRecPtr callBackParms;
callBackParms = ccbi->callBackParms;
AECreateDesc (typeFSS, &spec, sizeof(FSSpec), &desc);
NavCustomControl(callBackParms->context, kNavCtlSetLocation, &desc);
AEDisposeDesc(&desc);
if (!ccbi->cbi->has_parent) {
::HideSheetWindow(dialog);
} else {
::HideWindow(dialog);
}
::QuitAppModalLoopForWindow(dialog);
} else
wxBell();
return noErr;
}
static OSStatus cancel_evt_handler(EventHandlerCallRef inHandlerCallRef,
EventRef inEvent,
void *inUserData)
{
wxCallbackCallbackInfo *cbbi = (wxCallbackCallbackInfo *)GET_SAFEREF(inUserData);
WindowRef dialog = cbbi->dialog;
::HideWindow(dialog);
::QuitAppModalLoopForWindow(dialog);
return noErr;
}
static OSStatus key_evt_handler(EventHandlerCallRef inHandlerCallRef,
EventRef inEvent,
void *inUserData)
{
char c;
GetEventParameter(inEvent, kEventParamKeyMacCharCodes, typeChar,
NULL, sizeof(c), NULL, &c);
if (c == 13) {
return ok_evt_handler(inHandlerCallRef, NULL, inUserData);
} else if (c == 27) {
return cancel_evt_handler(inHandlerCallRef, NULL, inUserData);
} else
return eventNotHandledErr;
}
static OSStatus tab_evt_handler(EventHandlerCallRef inHandlerCallRef,
EventRef inEvent,
void *inUserData)
{
char c;
GetEventParameter(inEvent, kEventParamKeyMacCharCodes, typeChar,
NULL, sizeof(c), NULL, &c);
if (c == 9) {
char *result;
int len;
wxCallbackCallbackInfo *ccbi = (wxCallbackCallbackInfo *)GET_SAFEREF(inUserData);
result = extract_string(ccbi);
len = strlen(result);
if (scheme_is_complete_path(result, len)) {
result = scheme_find_completion(result);
} else
result = NULL;
if (result) {
CFStringRef str;
str = wxCFString(result);
::SetControlData(ccbi->txt, kControlEntireControl,
kControlEditTextCFStringTag, sizeof(CFStringRef), &str);
::CFRelease(str);
::Draw1Control(ccbi->txt);
} else
wxBell();
return noErr;
} else
return eventNotHandledErr;
}
static char *extract_current_dir(NavCBRecPtr callBackParms)
{
AEDesc here, there;
FSRef fsref;
OSErr err;
char *dir = NULL;
NavCustomControl(callBackParms->context, kNavCtlGetLocation, &here);
err = AECoerceDesc(&here, typeFSRef, &there);
if (err != noErr) {
if (err == errAECoercionFail) {
/* Try FSSpec: */
FSSpec spec;
err = AECoerceDesc(&here, typeFSRef, &there);
if (err == noErr) {
err = AEGetDescData(&there, &spec, sizeof(FSSpec));
if (err == noErr)
dir = scheme_mac_spec_to_path(&spec);
AEDisposeDesc(&there);
}
}
} else {
err = AEGetDescData(&there, &fsref, sizeof(fsref));
if (err == noErr)
dir = wxFSRefToPath(fsref);
AEDisposeDesc(&there);
}
return dir;
}
static void do_text_path_dialog(wxCallbackInfo *cbi,
NavCBRecPtr callBackParms)
{
int width = 500;
WindowRef parent, dialog;
ControlRef ok, lbl, txt, cancel;
EventTypeSpec spec[1];
Rect r, pr;
char byteFlag = 1, *init;
ControlFontStyleRec style;
ControlEditTextSelectionRec sel;
wxCallbackCallbackInfo *info;
CFStringRef str;
void *info_sr;
info = new wxCallbackCallbackInfo;
info_sr = WRAP_SAFEREF(info);
init = extract_current_dir(callBackParms);
if (!init)
init = "/";
parent = ::NavDialogGetWindow(cbi->dialog);
GetWindowBounds(parent, kWindowContentRgn, &pr);
::SetRect(&r, 0, 0, width, 90);
r.top += ((pr.top + pr.bottom) - r.bottom) / 2;
r.bottom += r.top;
r.left = ((pr.left + pr.right) - r.right) / 2;
r.right += r.left;
::CreateNewWindow(cbi->has_parent ? kMovableModalWindowClass : kSheetWindowClass,
kWindowCompositingAttribute, &r, &dialog);
::InstallStandardEventHandler(GetWindowEventTarget(dialog));
spec[0].eventClass = kEventClassKeyboard;
spec[0].eventKind = kEventRawKeyDown;
info->dialog = dialog;
info->cbi = cbi;
::InstallEventHandler(GetWindowEventTarget(dialog), key_evt_handler, 1, spec, info_sr, NULL);
style.flags = kControlUseFontMask;
style.font = kControlFontBigSystemFont;
::SetRect(&r, 10, 10, width - 10, 26);
::CreateStaticTextControl(dialog, &r, CFSTR("Go to the folder:"), &style, &lbl);
::ShowControl(lbl);
::SetRect(&r, 10, 32, width - 10, 48);
str = wxCFString(init);
::CreateEditTextControl(dialog, &r, str, 0, 0, &style, &txt);
:: CFRelease(str);
spec[0].eventClass = kEventClassKeyboard;
spec[0].eventKind = kEventRawKeyDown;
::InstallEventHandler(GetControlEventTarget(txt), tab_evt_handler, 1, spec, info_sr, NULL);
::ShowControl(txt);
info->txt = txt;
info->callBackParms = callBackParms;
::SetRect(&r, width - 75, 60, width - 10, 80);
::CreatePushButtonControl(dialog, &r, CFSTR("Goto"), &ok);
::ShowControl(ok);
spec[0].eventClass = kEventClassControl;
spec[0].eventKind = kEventControlHit;
::InstallEventHandler(GetControlEventTarget(ok), ok_evt_handler, 1, spec, info_sr, NULL);
::SetControlData(ok, kControlEntireControl, kControlPushButtonDefaultTag, 1, &byteFlag);
::SetRect(&r, width - 150, 60, width - 85, 80);
::CreatePushButtonControl(dialog, &r, CFSTR("Cancel"), &cancel);
::ShowControl(cancel);
::InstallEventHandler(GetControlEventTarget(cancel), cancel_evt_handler, 1, spec, info_sr, NULL);
::SetKeyboardFocus(dialog, txt, kControlFocusNextPart);
sel.selStart = 1;
sel.selEnd = 1000;
::SetControlData(txt, kControlEntireControl, kControlEditTextSelectionTag, sizeof(sel), &sel);
if (!cbi->has_parent) {
::ShowSheetWindow(dialog, parent);
} else {
::ShowWindow(dialog);
}
::RunAppModalLoopForWindow(dialog);
::DisposeControl(lbl);
::DisposeControl(txt);
::DisposeControl(ok);
::DisposeControl(cancel);
::DisposeWindow(dialog);
FREE_SAFEREF(info_sr);
info_sr = NULL;
}
//-----------------------------------------------------------------------------
// File-selector callback
//-----------------------------------------------------------------------------
/* Sets the right initial directory, if one is supplied, and
redirects '/' to open the text path dialog. */
static void ExtensionCallback(NavEventCallbackMessage callBackSelector,
NavCBRecPtr callBackParms,
void *callBackUD)
{
wxCallbackInfo *cbi = (wxCallbackInfo *)callBackUD;
wxCallbackInfo *cbi = (wxCallbackInfo *)GET_SAFEREF(callBackUD);
switch (callBackSelector) {
case kNavCBEvent:
if ((callBackParms->eventData.eventDataParms.event->what == keyUp)
&& ((callBackParms->eventData.eventDataParms.event->message & charCodeMask) == '/')) {
do_text_path_dialog(cbi, callBackParms);
}
break;
case kNavCBStart:
if (cbi->initial_directory) {
FSSpec spec;
@ -298,93 +578,6 @@ static void ExtensionCallback(NavEventCallbackMessage callBackSelector,
}
break;
case kNavCBAccept:
if (cbi->force_extension) {
Str255 sv;
StringPtr s;
char *c, *suffix = cbi->force_extension;
int i, sl;
s = sv;
NavCustomControl(callBackParms->context, kNavCtlGetEditFileName, s);
c = wxP2C(s);
for (i = s[0]; i--; ) {
if (c[i] == '.')
break;
}
if (i < 0)
i = 0;
if (strcmp(c + i, suffix)) {
unsigned char *s2;
sl = strlen(suffix);
s2 = (unsigned char *)(new WXGC_ATOMIC char[s[0] + sl + 1]);
memcpy(s2 + 1, s + 1, s[0]);
memcpy(s2 + 1 + s[0], suffix, sl);
s2[0] = s[0] + sl;
NavCustomControl(callBackParms->context, kNavCtlSetEditFileName, s2);
s = s2;
}
{
AEDesc here, there;
FSRef fsref;
OSErr err;
char *dir = NULL;
NavCustomControl(callBackParms->context, kNavCtlGetLocation, &here);
err = AECoerceDesc(&here, typeFSRef, &there);
if (err != noErr) {
if (err == errAECoercionFail) {
/* Try FSSpec: */
FSSpec spec;
err = AECoerceDesc(&here, typeFSRef, &there);
if (err == noErr) {
err = AEGetDescData(&there, &spec, sizeof(FSSpec));
if (err == noErr)
dir = scheme_mac_spec_to_path(&spec);
AEDisposeDesc(&there);
}
}
} else {
err = AEGetDescData(&there, &fsref, sizeof(fsref));
if (err == noErr)
dir = wxFSRefToPath(fsref);
AEDisposeDesc(&there);
}
if (!dir)
printf("NoDir! %d\n", err);
if (dir) {
AlertStdAlertParamRec rec;
SInt16 which;
rec.movable = FALSE;
rec.helpButton = FALSE;
rec.filterProc = NULL;
rec.defaultText = "\pReplace";
rec.cancelText = (ConstStringPtr)kAlertDefaultCancelText;
rec.otherText = NULL;
rec.defaultButton = kAlertStdAlertCancelButton;
rec.cancelButton = 0;
rec.position = kWindowAlertPositionParentWindowScreen;
which = kAlertStdAlertCancelButton;
err = StandardAlert(kAlertCautionAlert,
"\pReally replace?",
NULL,
&rec,
&which);
if (which == kAlertStdAlertCancelButton) {
/* ??????? */
}
}
}
}
case kNavCBCancel: /* ^^^^^^^^^^ FALLTHROUGH ^^^^^^^^^^^^ */
QuitAppModalLoopForWindow(callBackParms->window);
break;
@ -431,6 +624,7 @@ char *wxFileSelector(char *message, char *default_path,
OSErr derr;
NavDialogCreationOptions dialogOptions;
wxCallbackInfo *cbi;
void *cbi_sr;
NavUserAction action;
NavReplyRecord *reply;
char *temp;
@ -448,14 +642,10 @@ char *wxFileSelector(char *message, char *default_path,
cbi = new wxCallbackInfo();
cbi->initial_directory = default_path;
cbi->force_extension = NULL;
NavGetDefaultDialogCreationOptions(&dialogOptions);
if (default_filename) {
dialogOptions.saveFileName = CFStringCreateWithCString(NULL,default_filename,CFStringGetSystemEncoding());
}
if (message) {
dialogOptions.message = CFStringCreateWithCString(NULL,message,CFStringGetSystemEncoding());
dialogOptions.message = wxCFString(message);
}
dialogOptions.modality = kWindowModalityAppModal;
@ -466,10 +656,48 @@ char *wxFileSelector(char *message, char *default_path,
if (!(flags & wxMULTIOPEN))
dialogOptions.optionFlags -= (dialogOptions.optionFlags & kNavAllowMultipleFiles);
if (cbi->force_extension)
dialogOptions.optionFlags |= kNavDontConfirmReplacement;
/* Check whether to enforce a particular suffix */
if (default_extension && wildcard && flags && !(flags & (wxOPEN | wxMULTIOPEN | wxGETDIR))) {
GC_CAN_IGNORE char *s1, *s2;
s1 = strchr(wildcard, '|');
if (s1) {
s1++;
s2 = strchr(s1, '|');
if (s2) {
int len, flen;
len = strlen(default_extension);
if ((s1[0] == '*')
&& (s1[1] == '.')
&& ((s2 - s1) == (len + 2))
&& !strncmp(default_extension, s1+2, len)) {
dialogOptions.optionFlags |= kNavPreserveSaveFileExtension;
/* Make sure initial name has specified extension: */
if (!default_filename)
default_filename = "?";
flen = strlen(default_filename);
if ((flen < len + 1)
|| (default_filename[flen -len - 1] != '.')
|| strcmp(default_extension, default_filename + flen - len)) {
/* Need to add extension */
char *naya;
naya = new WXGC_ATOMIC char[flen + len +2];
memcpy(naya, default_filename, flen);
memcpy(naya + flen + 1, default_extension, len + 1);
naya[flen] = '.';
default_filename = naya;
}
}
}
}
}
if (default_filename) {
dialogOptions.saveFileName = wxCFString(default_filename);
}
cbi->has_parent = 1;
#ifdef OS_X
if (parent) {
wxFrame *f;
@ -490,25 +718,29 @@ char *wxFileSelector(char *message, char *default_path,
graf = mdc->macGrafPort();
dialogOptions.parentWindow = GetWindowFromPort(graf);
dialogOptions.modality = kWindowModalityWindowModal;
cbi->has_parent = 1;
}
}
#endif
cbi_sr = WRAP_SAFEREF(cbi);
// create the dialog:
if (flags & wxGETDIR) {
derr = NavCreateChooseFolderDialog(&dialogOptions,
extProc, NULL, cbi,
extProc, NULL, cbi_sr,
&outDialog);
} else if ((flags == 0) || (flags & wxOPEN) || (flags & wxMULTIOPEN)) {
derr = NavCreateGetFileDialog(&dialogOptions, NULL,
extProc, NULL, NULL, cbi,
extProc, NULL, NULL, cbi_sr,
&outDialog);
} else {
derr = NavCreatePutFileDialog(&dialogOptions, 'TEXT', 'mReD',
extProc, cbi,
extProc, cbi_sr,
&outDialog);
}
cbi->dialog = outDialog;
if (derr != noErr) {
if (default_filename)
CFRelease(dialogOptions.saveFileName);
@ -527,6 +759,8 @@ char *wxFileSelector(char *message, char *default_path,
CFRelease(dialogOptions.message);
NavDialogDispose(outDialog);
wxTheApp->AdjustCursor();
FREE_SAFEREF(cbi_sr);
cbi_sr = NULL;
return NULL;
}
@ -536,6 +770,9 @@ char *wxFileSelector(char *message, char *default_path,
wxPrimDialogCleanUp();
FREE_SAFEREF(cbi_sr);
cbi_sr = NULL;
// dump those strings:
if (default_filename)
CFRelease(dialogOptions.saveFileName);

View File

@ -145,29 +145,6 @@ extern "C" {
CFStringRef wxCFString(const char *s)
{
int l, ul, i;
unsigned int *us;
/* Look for a character that is beyond the official Unicode
range, which ends at 0x10FFFDL. */
l = strlen(s);
us = new WXGC_ATOMIC unsigned[l + 1];
ul = scheme_utf8_decode_all((unsigned char *)s, l, us, 0);
for (i = 0; i < ul; i++) {
if (us[i] > 0x10FFFD) {
us[i] = '?';
s = NULL;
}
}
if (!s) {
/* Found a too-large char. Convert back to utf-8.
(The result will be smaller than the old l.) */
s = new WXGC_ATOMIC char[l + 1];
l = scheme_utf8_encode_all(us, ul, (unsigned char *)s);
((char *)s)[l] = 0;
}
return CFStringCreateWithCString(NULL, s, kCFStringEncodingUTF8);
}