diff options
author | fvogel <fvogelnew1@free.fr> | 2017-06-05 18:32:24 (GMT) |
---|---|---|
committer | fvogel <fvogelnew1@free.fr> | 2017-06-05 18:32:24 (GMT) |
commit | fbac4859a673c9a5f0c8936ed8d18ea9e9145304 (patch) | |
tree | 4e184d638205d9ce2ef854ebea9393e5d8d91bd3 /macosx | |
parent | 452ee6a6849e04a6a94bc7488e935129614041f8 (diff) | |
parent | fd3fd3d844d9ff5f83c3fd26ee88f2c02892c180 (diff) | |
download | tk-fbac4859a673c9a5f0c8936ed8d18ea9e9145304.zip tk-fbac4859a673c9a5f0c8936ed8d18ea9e9145304.tar.gz tk-fbac4859a673c9a5f0c8936ed8d18ea9e9145304.tar.bz2 |
merge trunk
Diffstat (limited to 'macosx')
-rw-r--r-- | macosx/tkMacOSXDialog.c | 555 | ||||
-rw-r--r-- | macosx/tkMacOSXFont.c | 2 | ||||
-rw-r--r-- | macosx/tkMacOSXScrlbr.c | 81 | ||||
-rw-r--r-- | macosx/tkMacOSXWm.c | 5 | ||||
-rw-r--r-- | macosx/tkMacOSXWm.h | 4 | ||||
-rw-r--r-- | macosx/tkMacOSXXStubs.c | 6 |
6 files changed, 432 insertions, 221 deletions
diff --git a/macosx/tkMacOSXDialog.c b/macosx/tkMacOSXDialog.c index 80a7a11..3397f71 100644 --- a/macosx/tkMacOSXDialog.c +++ b/macosx/tkMacOSXDialog.c @@ -6,6 +6,7 @@ * Copyright (c) 1996-1997 Sun Microsystems, Inc. * Copyright 2001-2009, Apple Inc. * Copyright (c) 2006-2009 Daniel A. Steffen <das@users.sourceforge.net> + * Copyright (c) 2017 Christian Gollwitzer. * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. @@ -24,6 +25,22 @@ #define modalOther -1 #define modalError -2 +/*Vars for filtering in "open file" and "save file" dialogs.*/ +typedef struct { + bool doFileTypes; // show the accessory view which displays the filter menu + bool preselectFilter; // a filter was selected by the typevariable + bool userHasSelectedFilter; // The user has changed the filter in the accessory view + NSMutableArray *fileTypeNames; // array of names, e.g. "Text document" + NSMutableArray *fileTypeExtensions; // array of allowed extensions per name, e.g. "txt", "doc" + NSMutableArray *fileTypeLabels; // displayed string, e.g. "Text document (.txt, .doc)" + NSMutableArray *allAllowedExtensions; // set of all allowed extensions + NSInteger fileTypeIndex; // index of currently selected filter +} filepanelFilterInfo; + +filepanelFilterInfo filterInfo; + +NSOpenPanel *openpanel; +NSSavePanel *savepanel; static const char *const colorOptionStrings[] = { "-initialcolor", "-parent", "-title", NULL @@ -142,22 +159,6 @@ static const short alertNativeButtonIndexAndTypeToButtonIndex[][3] = { [TYPE_YESNOCANCEL] = {5, 6, 4}, }; -/* - * Construct a file URL from directory and filename. Either may - * be nil. If both are nil, returns nil. - */ -#if MAC_OS_X_VERSION_MIN_REQUIRED > 1050 -static NSURL *getFileURL(NSString *directory, NSString *filename) { - NSURL *url = nil; - if (directory) { - url = [NSURL fileURLWithPath:directory]; - } - if (filename) { - url = [NSURL URLWithString:filename relativeToURL:url]; - } - return url; -} -#endif #pragma mark TKApplication(TKDialog) @@ -212,6 +213,7 @@ static NSURL *getFileURL(NSString *directory, NSString *filename) { } } + - (void) tkAlertDidEnd: (NSAlert *) alert returnCode: (NSInteger) returnCode contextInfo: (void *) contextInfo { @@ -247,6 +249,23 @@ static NSURL *getFileURL(NSString *directory, NSString *filename) { ckfree(callbackInfo); } } + +- (void)selectFormat:(id)sender { + NSPopUpButton *button = (NSPopUpButton *)sender; + filterInfo.fileTypeIndex = [button indexOfSelectedItem]; + NSMutableArray *allowedtypes = filterInfo.fileTypeExtensions[filterInfo.fileTypeIndex]; + [openpanel setAllowedFileTypes:allowedtypes]; + filterInfo.userHasSelectedFilter = true; + +} + +- (void)saveFormat:(id)sender { + NSPopUpButton *button = (NSPopUpButton *)sender; + filterInfo.fileTypeIndex = [button indexOfSelectedItem]; + NSMutableArray *allowedtypes = filterInfo.fileTypeExtensions[filterInfo.fileTypeIndex]; + [savepanel setAllowedFileTypes:allowedtypes]; +} + @end #pragma mark - @@ -360,6 +379,98 @@ Tk_ChooseColorObjCmd( end: return result; } + +/* dissect the -filetype nested lists and store the information + * in the filterInfo structure */ +int parseFileFilters(Tcl_Interp *interp, Tcl_Obj *fileTypesPtr, Tcl_Obj *typeVariablePtr) { + + if (!fileTypesPtr) { + filterInfo.doFileTypes = false; + return TCL_OK; + } + + FileFilterList fl; + TkInitFileFilters(&fl); + if (TkGetFileFilters(interp, &fl, fileTypesPtr, 0) != TCL_OK) { + TkFreeFileFilters(&fl); + return TCL_ERROR; + } + + filterInfo.doFileTypes = (fl.filters != NULL); + + filterInfo.fileTypeIndex = 0; + filterInfo.fileTypeExtensions = [NSMutableArray array]; + filterInfo.fileTypeNames = [NSMutableArray array]; + filterInfo.fileTypeLabels = [NSMutableArray array]; + filterInfo.allAllowedExtensions = [NSMutableArray array]; + + if (filterInfo.doFileTypes) { + for (FileFilter *filterPtr = fl.filters; filterPtr; + filterPtr = filterPtr->next) { + NSString * name = [[NSString alloc] initWithUTF8String: filterPtr -> name]; + [filterInfo.fileTypeNames addObject:name]; + [name release]; + NSMutableArray * clauseextensions = [NSMutableArray array]; + NSMutableArray * displayextensions = [NSMutableArray array]; + + for (FileFilterClause *clausePtr = filterPtr->clauses; clausePtr; + clausePtr = clausePtr->next) { + for (GlobPattern *globPtr = clausePtr->patterns; globPtr; + globPtr = globPtr->next) { + const char *str = globPtr->pattern; + while (*str && (*str == '*' || *str == '.')) { + str++; + } + if (*str) { + NSString *extension = [[NSString alloc] initWithUTF8String:str]; + if (![filterInfo.allAllowedExtensions containsObject:extension]) { + [filterInfo.allAllowedExtensions addObject:extension]; + } + + [clauseextensions addObject:extension]; + [displayextensions addObject:[@"." stringByAppendingString:extension]]; + + [extension release]; + } + } + } + [filterInfo.fileTypeExtensions addObject:clauseextensions]; + + NSMutableString * label = [[NSMutableString alloc] initWithString:name]; + [label appendString:@" ("]; + [label appendString:[displayextensions componentsJoinedByString:@", "]]; + [label appendString:@")"]; + [filterInfo.fileTypeLabels addObject:label]; + [label release]; + + } + + /* Check if the typevariable exists and matches one of the names */ + filterInfo.preselectFilter = false; + filterInfo.userHasSelectedFilter = false; + if (typeVariablePtr) { + /* extract the variable content as a NSString */ + Tcl_Obj *selectedFileTypeObj = Tcl_ObjGetVar2(interp, typeVariablePtr, NULL, TCL_GLOBAL_ONLY); + + /* check that the typevariable exists */ + if (selectedFileTypeObj != NULL) { + const char *selectedFileType = Tcl_GetString(selectedFileTypeObj); + NSString *selectedFileTypeStr = [[NSString alloc] initWithUTF8String:selectedFileType]; + NSUInteger index = [filterInfo.fileTypeNames indexOfObject:selectedFileTypeStr]; + + if (index != NSNotFound) { + filterInfo.fileTypeIndex = index; + filterInfo.preselectFilter = true; + } + } + } + + } + + TkFreeFileFilters(&fl); + return TCL_OK; +} + /* *---------------------------------------------------------------------- @@ -388,19 +499,16 @@ Tk_GetOpenFileObjCmd( char *str; int i, result = TCL_ERROR, haveParentOption = 0; int index, len, multiple = 0; - FileFilterList fl; - Tcl_Obj *cmdObj = NULL, *typeVariablePtr = NULL; + Tcl_Obj *cmdObj = NULL, *typeVariablePtr = NULL, *fileTypesPtr = NULL; FilePanelCallbackInfo callbackInfoStruct; FilePanelCallbackInfo *callbackInfo = &callbackInfoStruct; NSString *directory = nil, *filename = nil; - NSString *message, *title, *type; + NSString *message = nil, *title = nil; NSWindow *parent; - NSMutableArray *fileTypes = nil; - NSOpenPanel *panel = [NSOpenPanel openPanel]; + openpanel = [NSOpenPanel openPanel]; NSInteger modalReturnCode = modalError; BOOL parentIsKey = NO; - TkInitFileFilters(&fl); for (i = 1; i < objc; i += 2) { if (Tcl_GetIndexFromObjStruct(interp, objv[i], openOptionStrings, sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) { @@ -416,9 +524,7 @@ Tk_GetOpenFileObjCmd( case OPEN_DEFAULT: break; case OPEN_FILETYPES: - if (TkGetFileFilters(interp, &fl, objv[i + 1], 0) != TCL_OK) { - goto end; - } + fileTypesPtr = objv[i + 1]; break; case OPEN_INITDIR: str = Tcl_GetStringFromObj(objv[i + 1], &len); @@ -432,13 +538,12 @@ Tk_GetOpenFileObjCmd( if (len) { filename = [[[NSString alloc] initWithUTF8String:str] autorelease]; + [openpanel setNameFieldStringValue:filename]; } break; case OPEN_MESSAGE: message = [[NSString alloc] initWithUTF8String: Tcl_GetString(objv[i + 1])]; - [panel setMessage:message]; - [message release]; break; case OPEN_MULTIPLE: if (Tcl_GetBooleanFromObj(interp, objv[i + 1], @@ -457,8 +562,6 @@ Tk_GetOpenFileObjCmd( case OPEN_TITLE: title = [[NSString alloc] initWithUTF8String: Tcl_GetString(objv[i + 1])]; - [panel setTitle:title]; - [title release]; break; case OPEN_TYPEVARIABLE: typeVariablePtr = objv[i + 1]; @@ -468,40 +571,70 @@ Tk_GetOpenFileObjCmd( break; } } - [panel setAllowsMultipleSelection:multiple]; - if (fl.filters) { - fileTypes = [NSMutableArray array]; - for (FileFilter *filterPtr = fl.filters; filterPtr; - filterPtr = filterPtr->next) { - for (FileFilterClause *clausePtr = filterPtr->clauses; clausePtr; - clausePtr = clausePtr->next) { - for (GlobPattern *globPtr = clausePtr->patterns; globPtr; - globPtr = globPtr->next) { - str = globPtr->pattern; - while (*str && (*str == '*' || *str == '.')) { - str++; - } - if (*str) { - type = [[NSString alloc] initWithUTF8String:str]; - if (![fileTypes containsObject:type]) { - [fileTypes addObject:type]; - } - [type release]; - } - } - for (MacFileType *mfPtr = clausePtr->macTypes; mfPtr; - mfPtr = mfPtr->next) { - if (mfPtr->type) { - type = NSFileTypeForHFSTypeCode(mfPtr->type); - if (![fileTypes containsObject:type]) { - [fileTypes addObject:type]; - } - } - } - } + + /* From OSX 10.11, the title string is silently ignored. + * Prepend the title to the message + * NOTE should be conditional on OSX version, but + * -mmacosx-version-min does not revert this behaviour*/ + if (title) { + [openpanel setTitle:title]; + if (message) { + NSString *fullmessage = [[NSString alloc] initWithFormat:@"%@\n%@",title,message]; + [message release]; + [title release]; + message = fullmessage; + } else { + message = title; + } + } + + if (message) { + [openpanel setMessage:message]; + [message release]; + } + + [openpanel setAllowsMultipleSelection:multiple]; + + if (parseFileFilters(interp, fileTypesPtr, typeVariablePtr) != TCL_OK) { + goto end; + } + + if (filterInfo.doFileTypes) { + NSView *accessoryView = [[NSView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 200, 32.0)]; + NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 60, 22)]; + [label setEditable:NO]; + [label setStringValue:@"Enable:"]; + [label setBordered:NO]; + [label setBezeled:NO]; + [label setDrawsBackground:NO]; + + NSPopUpButton *popupButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(50.0, 2, 140, 22.0) pullsDown:NO]; + [popupButton addItemsWithTitles:filterInfo.fileTypeLabels]; + [popupButton setAction:@selector(selectFormat:)]; + + [accessoryView addSubview:label]; + [accessoryView addSubview:popupButton]; + + if (filterInfo.preselectFilter) { + /* A specific filter was selected from the typevariable. Select it and + * open the accessory view */ + [popupButton selectItemAtIndex:filterInfo.fileTypeIndex]; + /* on OSX > 10.11, the optons are not visible by default. Ergo allow all file types + [openpanel setAllowedFileTypes:filterInfo.fileTypeExtensions[filterInfo.fileTypeIndex]]; + */ + [openpanel setAllowedFileTypes:filterInfo.allAllowedExtensions]; + } else { + [openpanel setAllowedFileTypes:filterInfo.allAllowedExtensions]; } + + [openpanel setAllowsOtherFileTypes:NO]; + + [openpanel setAccessoryView:accessoryView]; + } else { + /* No filters are given. Allow picking all files */ + [openpanel setAllowsOtherFileTypes:YES]; } - [panel setAllowedFileTypes:fileTypes]; + if (cmdObj) { callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo)); if (Tcl_IsShared(cmdObj)) { @@ -509,6 +642,7 @@ Tk_GetOpenFileObjCmd( } Tcl_IncrRefCount(cmdObj); } + callbackInfo->cmdObj = cmdObj; callbackInfo->interp = interp; callbackInfo->multiple = multiple; @@ -516,52 +650,63 @@ Tk_GetOpenFileObjCmd( if (haveParentOption && parent && ![parent attachedSheet]) { parentIsKey = [parent isKeyWindow]; #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 - [panel beginSheetForDirectory:directory + [openpanel beginSheetForDirectory:directory file:filename - types:fileTypes + types:openFileTypes modalForWindow:parent modalDelegate:NSApp didEndSelector: @selector(tkFilePanelDidEnd:returnCode:contextInfo:) contextInfo:callbackInfo]; #else - [panel setAllowedFileTypes:fileTypes]; - [panel setDirectoryURL:getFileURL(directory, filename)]; - [panel beginSheetModalForWindow:parent + if (directory) { + [openpanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]]; + } + [openpanel setNameFieldStringValue:filename]; + [openpanel beginSheetModalForWindow:parent completionHandler:^(NSInteger returnCode) - { [NSApp tkFilePanelDidEnd:panel + { [NSApp tkFilePanelDidEnd:openpanel returnCode:returnCode contextInfo:callbackInfo ]; } ]; #endif - modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:panel]; + modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:openpanel]; } else { #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 - modalReturnCode = [panel runModalForDirectory:directory + modalReturnCode = [openpanel runModalForDirectory:directory file:filename]; #else - [panel setDirectoryURL:getFileURL(directory, filename)]; - modalReturnCode = [panel runModal]; + if (directory) { + [openpanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]]; + } + [openpanel setNameFieldStringValue:filename]; + modalReturnCode = [openpanel runModal]; #endif - [NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode + [NSApp tkFilePanelDidEnd:openpanel returnCode:modalReturnCode contextInfo:callbackInfo]; } result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR; if (parentIsKey) { [parent makeKeyWindow]; } - if (typeVariablePtr && result == TCL_OK) { + + if ((typeVariablePtr && (modalReturnCode == NSOKButton)) && + filterInfo.doFileTypes && filterInfo.userHasSelectedFilter) { /* - * The -typevariable option is not really supported. + * The -typevariable must be set to the selected file type, if the dialog was not cancelled */ - - Tcl_SetVar2(interp, Tcl_GetString(typeVariablePtr), NULL, - "", TCL_GLOBAL_ONLY); + #if 0 + NSLog(@"result: %i modal: %li", result, (long)modalReturnCode); + #endif + NSString * selectedFilter = filterInfo.fileTypeNames[filterInfo.fileTypeIndex]; + Tcl_ObjSetVar2(interp, typeVariablePtr, NULL, + Tcl_NewStringObj([selectedFilter UTF8String], -1), TCL_GLOBAL_ONLY); } + end: - TkFreeFileFilters(&fl); return result; } + /* *---------------------------------------------------------------------- @@ -591,19 +736,16 @@ Tk_GetSaveFileObjCmd( int i, result = TCL_ERROR, haveParentOption = 0; int confirmOverwrite = 1; int index, len; - FileFilterList fl; - Tcl_Obj *cmdObj = NULL; + Tcl_Obj *cmdObj = NULL, *typeVariablePtr = NULL, *fileTypesPtr = NULL; FilePanelCallbackInfo callbackInfoStruct; FilePanelCallbackInfo *callbackInfo = &callbackInfoStruct; NSString *directory = nil, *filename = nil, *defaultType = nil; - NSString *message, *title, *type; + NSString *message = nil, *title = nil; NSWindow *parent; - NSMutableArray *fileTypes = nil; - NSSavePanel *panel = [NSSavePanel savePanel]; + savepanel = [NSSavePanel savePanel]; NSInteger modalReturnCode = modalError; BOOL parentIsKey = NO; - TkInitFileFilters(&fl); for (i = 1; i < objc; i += 2) { if (Tcl_GetIndexFromObjStruct(interp, objv[i], saveOptionStrings, sizeof(char *), "option", TCL_EXACT, &index) != TCL_OK) { @@ -616,96 +758,120 @@ Tk_GetSaveFileObjCmd( goto end; } switch (index) { - case SAVE_DEFAULT: - str = Tcl_GetStringFromObj(objv[i + 1], &len); - while (*str && (*str == '*' || *str == '.')) { - str++; - } - if (*str) { - defaultType = [[[NSString alloc] initWithUTF8String:str] - autorelease]; - } - break; - case SAVE_FILETYPES: - if (TkGetFileFilters(interp, &fl, objv[i + 1], 0) != TCL_OK) { - goto end; - } - break; - case SAVE_INITDIR: - str = Tcl_GetStringFromObj(objv[i + 1], &len); - if (len) { - directory = [[[NSString alloc] initWithUTF8String:str] - autorelease]; - } - break; - case SAVE_INITFILE: - str = Tcl_GetStringFromObj(objv[i + 1], &len); - if (len) { - filename = [[[NSString alloc] initWithUTF8String:str] - autorelease]; - } - break; - case SAVE_MESSAGE: - message = [[NSString alloc] initWithUTF8String: - Tcl_GetString(objv[i + 1])]; - [panel setMessage:message]; + case SAVE_DEFAULT: + str = Tcl_GetStringFromObj(objv[i + 1], &len); + while (*str && (*str == '*' || *str == '.')) { + str++; + } + if (*str) { + defaultType = [[[NSString alloc] initWithUTF8String:str] + autorelease]; + } + break; + case SAVE_FILETYPES: + fileTypesPtr = objv[i + 1]; + break; + case SAVE_INITDIR: + str = Tcl_GetStringFromObj(objv[i + 1], &len); + if (len) { + directory = [[[NSString alloc] initWithUTF8String:str] + autorelease]; + } + break; + case SAVE_INITFILE: + str = Tcl_GetStringFromObj(objv[i + 1], &len); + if (len) { + filename = [[[NSString alloc] initWithUTF8String:str] + autorelease]; + [savepanel setNameFieldStringValue:filename]; + } + break; + case SAVE_MESSAGE: + message = [[NSString alloc] initWithUTF8String: + Tcl_GetString(objv[i + 1])]; + break; + case SAVE_PARENT: + str = Tcl_GetStringFromObj(objv[i + 1], &len); + tkwin = Tk_NameToWindow(interp, str, tkwin); + if (!tkwin) { + goto end; + } + haveParentOption = 1; + break; + case SAVE_TITLE: + title = [[NSString alloc] initWithUTF8String: + Tcl_GetString(objv[i + 1])]; + break; + case SAVE_TYPEVARIABLE: + typeVariablePtr = objv[i + 1]; + break; + case SAVE_COMMAND: + cmdObj = objv[i+1]; + break; + case SAVE_CONFIRMOW: + if (Tcl_GetBooleanFromObj(interp, objv[i + 1], + &confirmOverwrite) != TCL_OK) { + goto end; + } + break; + } + } + + if (title) { + [savepanel setTitle:title]; + if (message) { + NSString *fullmessage = [[NSString alloc] initWithFormat:@"%@\n%@",title,message]; [message release]; - break; - case SAVE_PARENT: - str = Tcl_GetStringFromObj(objv[i + 1], &len); - tkwin = Tk_NameToWindow(interp, str, tkwin); - if (!tkwin) { - goto end; - } - haveParentOption = 1; - break; - case SAVE_TITLE: - title = [[NSString alloc] initWithUTF8String: - Tcl_GetString(objv[i + 1])]; - [panel setTitle:title]; [title release]; - break; - case SAVE_TYPEVARIABLE: - break; - case SAVE_COMMAND: - cmdObj = objv[i+1]; - break; - case SAVE_CONFIRMOW: - if (Tcl_GetBooleanFromObj(interp, objv[i + 1], - &confirmOverwrite) != TCL_OK) { - goto end; - } - break; + message = fullmessage; + } else { + message = title; } } - if (fl.filters || defaultType) { - fileTypes = [NSMutableArray array]; - [fileTypes addObject:defaultType ? defaultType : (id)kUTTypeContent]; - for (FileFilter *filterPtr = fl.filters; filterPtr; - filterPtr = filterPtr->next) { - for (FileFilterClause *clausePtr = filterPtr->clauses; clausePtr; - clausePtr = clausePtr->next) { - for (GlobPattern *globPtr = clausePtr->patterns; globPtr; - globPtr = globPtr->next) { - str = globPtr->pattern; - while (*str && (*str == '*' || *str == '.')) { - str++; - } - if (*str) { - type = [[NSString alloc] initWithUTF8String:str]; - if (![fileTypes containsObject:type]) { - [fileTypes addObject:type]; - } - [type release]; - } - } - } - } - [panel setAllowedFileTypes:fileTypes]; - [panel setAllowsOtherFileTypes:YES]; + + if (message) { + [savepanel setMessage:message]; + [message release]; + } + + if (parseFileFilters(interp, fileTypesPtr, typeVariablePtr) != TCL_OK) { + goto end; } - [panel setCanSelectHiddenExtension:YES]; - [panel setExtensionHidden:NO]; + + if (filterInfo.doFileTypes) { + NSView *accessoryView = [[NSView alloc] initWithFrame:NSMakeRect(0.0, 0.0, 200, 32.0)]; + NSTextField *label = [[NSTextField alloc] initWithFrame:NSMakeRect(0, 0, 60, 22)]; + [label setEditable:NO]; + [label setStringValue:NSLocalizedString(@"Format:", nil)]; + [label setBordered:NO]; + [label setBezeled:NO]; + [label setDrawsBackground:NO]; + + NSPopUpButton *popupButton = [[NSPopUpButton alloc] initWithFrame:NSMakeRect(50.0, 2, 140, 22.0) pullsDown:NO]; + [popupButton addItemsWithTitles:filterInfo.fileTypeLabels]; + [popupButton selectItemAtIndex:filterInfo.fileTypeIndex]; + [popupButton setAction:@selector(saveFormat:)]; + + [accessoryView addSubview:label]; + [accessoryView addSubview:popupButton]; + + [savepanel setAccessoryView:accessoryView]; + + [savepanel setAllowedFileTypes:filterInfo.fileTypeExtensions[filterInfo.fileTypeIndex]]; + [savepanel setAllowsOtherFileTypes:NO]; + } else if (defaultType) { + /* If no filetypes are given, defaultextension is an alternative way + * to specify the attached extension. Just propose this extension, + * but don't display an accessory view */ + NSMutableArray *AllowedFileTypes = [NSMutableArray array]; + [AllowedFileTypes addObject:defaultType]; + [savepanel setAllowedFileTypes:AllowedFileTypes]; + [savepanel setAllowsOtherFileTypes:YES]; + } + + [savepanel setCanSelectHiddenExtension:YES]; + [savepanel setExtensionHidden:NO]; + if (cmdObj) { callbackInfo = ckalloc(sizeof(FilePanelCallbackInfo)); if (Tcl_IsShared(cmdObj)) { @@ -716,11 +882,12 @@ Tk_GetSaveFileObjCmd( callbackInfo->cmdObj = cmdObj; callbackInfo->interp = interp; callbackInfo->multiple = 0; + parent = TkMacOSXDrawableWindow(((TkWindow *) tkwin)->window); if (haveParentOption && parent && ![parent attachedSheet]) { parentIsKey = [parent isKeyWindow]; #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 - [panel beginSheetForDirectory:directory + [savepanel beginSheetForDirectory:directory file:filename modalForWindow:parent modalDelegate:NSApp @@ -728,30 +895,52 @@ Tk_GetSaveFileObjCmd( @selector(tkFilePanelDidEnd:returnCode:contextInfo:) contextInfo:callbackInfo]; #else - [panel setDirectoryURL:getFileURL(directory, filename)]; - [panel beginSheetModalForWindow:parent + if (directory) { + [savepanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]]; + } + [savepanel setNameFieldStringValue:filename]; + [savepanel beginSheetModalForWindow:parent completionHandler:^(NSInteger returnCode) - { [NSApp tkFilePanelDidEnd:panel + { [NSApp tkFilePanelDidEnd:savepanel returnCode:returnCode contextInfo:callbackInfo ]; } ]; #endif - modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:panel]; + modalReturnCode = cmdObj ? modalOther : [NSApp runModalForWindow:savepanel]; } else { #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 - modalReturnCode = [panel runModalForDirectory:directory file:filename]; + modalReturnCode = [savepanel runModalForDirectory:directory file:filename]; #else - [panel setDirectoryURL:getFileURL(directory, filename)]; - modalReturnCode = [panel runModal]; + if (directory) { + [savepanel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]]; + } + [savepanel setNameFieldStringValue:filename]; + modalReturnCode = [savepanel runModal]; + #if 0 + NSLog(@"modal: %li", modalReturnCode); + #endif #endif - [NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode + [NSApp tkFilePanelDidEnd:savepanel returnCode:modalReturnCode contextInfo:callbackInfo]; } result = (modalReturnCode != modalError) ? TCL_OK : TCL_ERROR; if (parentIsKey) { [parent makeKeyWindow]; } + + if ((typeVariablePtr && (modalReturnCode == NSOKButton)) && filterInfo.doFileTypes) { + /* + * The -typevariable must be set to the selected file type, if the dialog was not cancelled + */ + #if 0 + NSLog(@"result: %i modal: %li", result, (long)modalReturnCode); + #endif + NSString * selectedFilter = filterInfo.fileTypeNames[filterInfo.fileTypeIndex]; + Tcl_ObjSetVar2(interp, typeVariablePtr, NULL, + Tcl_NewStringObj([selectedFilter UTF8String], -1), TCL_GLOBAL_ONLY); + } + + end: - TkFreeFileFilters(&fl); return result; } @@ -787,7 +976,7 @@ Tk_ChooseDirectoryObjCmd( Tcl_Obj *cmdObj = NULL; FilePanelCallbackInfo callbackInfoStruct; FilePanelCallbackInfo *callbackInfo = &callbackInfoStruct; - NSString *directory = nil, *filename = nil; + NSString *directory = nil; NSString *message, *title; NSWindow *parent; NSOpenPanel *panel = [NSOpenPanel openPanel]; @@ -863,13 +1052,13 @@ Tk_ChooseDirectoryObjCmd( parentIsKey = [parent isKeyWindow]; #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 [panel beginSheetForDirectory:directory - file:filename + file:nil modalForWindow:parent modalDelegate:NSApp didEndSelector: @selector(tkFilePanelDidEnd:returnCode:contextInfo:) contextInfo:callbackInfo]; #else - [panel setDirectoryURL:getFileURL(directory, filename)]; + [panel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]]; [panel beginSheetModalForWindow:parent completionHandler:^(NSInteger returnCode) { [NSApp tkFilePanelDidEnd:panel @@ -881,7 +1070,7 @@ Tk_ChooseDirectoryObjCmd( #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060 modalReturnCode = [panel runModalForDirectory:directory file:nil]; #else - [panel setDirectoryURL:getFileURL(directory, filename)]; + [panel setDirectoryURL:[NSURL fileURLWithPath:directory isDirectory:YES]]; modalReturnCode = [panel runModal]; #endif [NSApp tkFilePanelDidEnd:panel returnCode:modalReturnCode diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c index b5ae1a3..fd4c19a 100644 --- a/macosx/tkMacOSXFont.c +++ b/macosx/tkMacOSXFont.c @@ -515,7 +515,7 @@ TkpGetFontFromAttributes( /* Set of attributes to match. */ { MacFont *fontPtr; - int points = TkFontGetPoints(tkwin, faPtr->size); + int points = (int)(TkFontGetPoints(tkwin, faPtr->size) + 0.5); NSFontTraitMask traits = GetNSFontTraitsFromTkFontAttributes(faPtr); NSInteger weight = (faPtr->weight == TK_FW_BOLD ? 9 : 5); NSFont *nsFont; diff --git a/macosx/tkMacOSXScrlbr.c b/macosx/tkMacOSXScrlbr.c index 91cf112..49ba999 100644 --- a/macosx/tkMacOSXScrlbr.c +++ b/macosx/tkMacOSXScrlbr.c @@ -19,6 +19,13 @@ #define MIN_SCROLLBAR_VALUE 0 +/* + * Minimum slider length, in pixels (designed to make sure that the slider is + * always easy to grab with the mouse). + */ + +#define MIN_SLIDER_LENGTH 5 + /*Borrowed from ttkMacOSXTheme.c to provide appropriate scaling of scrollbar values.*/ #ifdef __LP64__ #define RangeToFactor(maximum) (((double) (INT_MAX >> 1)) / (maximum)) @@ -60,16 +67,14 @@ typedef struct ScrollbarMetrics { } ScrollbarMetrics; static ScrollbarMetrics metrics[2] = { - {15, 54, 26, 14, 14, NSRegularControlSize}, /* kThemeScrollBarMedium */ - {11, 40, 20, 10, 10, NSSmallControlSize}, /* kThemeScrollBarSmall */ + {15, 54, 26, 14, 14, kControlSizeNormal}, /* kThemeScrollBarMedium */ + {11, 40, 20, 10, 10, kControlSizeSmall}, /* kThemeScrollBarSmall */ }; - HIThemeTrackDrawInfo info = { .version = 0, .min = 0.0, .max = 100.0, .attributes = kThemeTrackShowThumb, - .kind = kThemeScrollBarMedium, }; @@ -107,7 +112,7 @@ TkpCreateScrollbar( scrollPtr->troughGC = None; scrollPtr->copyGC = None; - Tk_CreateEventHandler(tkwin,ExposureMask|StructureNotifyMask|FocusChangeMask|ButtonPressMask|VisibilityChangeMask, ScrollbarEventProc, scrollPtr); + Tk_CreateEventHandler(tkwin,ExposureMask|StructureNotifyMask|FocusChangeMask|ButtonPressMask|ButtonReleaseMask|EnterWindowMask|LeaveWindowMask|VisibilityChangeMask, ScrollbarEventProc, scrollPtr); return (TkScrollbar *) scrollPtr; } @@ -212,7 +217,8 @@ TkpDisplayScrollbar( *---------------------------------------------------------------------- */ -extern void + + extern void TkpComputeScrollbarGeometry( register TkScrollbar *scrollPtr) /* Scrollbar whose geometry may have @@ -259,14 +265,12 @@ TkpComputeScrollbarGeometry( if (scrollPtr->sliderLast > fieldLength) { scrollPtr->sliderLast = fieldLength; } - if (!(MOUNTAIN_LION_STYLE)) { - scrollPtr->sliderFirst += scrollPtr->inset + - metrics[variant].topArrowHeight; - scrollPtr->sliderLast += scrollPtr->inset + - metrics[variant].bottomArrowHeight; - } - /* - * Register the desired geometry for the window (leave enough space + + scrollPtr->sliderFirst += scrollPtr->arrowLength + scrollPtr->inset; + scrollPtr->sliderLast += scrollPtr->arrowLength + scrollPtr->inset; + + + /* Register the desired geometry for the window (leave enough space * for the two arrows plus a minimum-size slider, plus border around * the whole window, if any). Then arrange for the window to be * redisplayed. @@ -281,6 +285,9 @@ TkpComputeScrollbarGeometry( } + + + /* *---------------------------------------------------------------------- * @@ -376,21 +383,22 @@ TkpScrollbarPosition( register const int arrowSize = scrollPtr->arrowLength + inset; if (scrollPtr->vertical) { - length = Tk_Height(scrollPtr->tkwin); - fieldlength = length - 2 * arrowSize; - width = Tk_Width(scrollPtr->tkwin); + length = Tk_Height(scrollPtr->tkwin); + fieldlength = length - 2 * arrowSize; + width = Tk_Width(scrollPtr->tkwin); } else { - tmp = x; - x = y; - y = tmp; - length = Tk_Width(scrollPtr->tkwin); - fieldlength = length - 2 * arrowSize; - width = Tk_Height(scrollPtr->tkwin); + tmp = x; + x = y; + y = tmp; + length = Tk_Width(scrollPtr->tkwin); + fieldlength = length - 2 * arrowSize; + width = Tk_Height(scrollPtr->tkwin); } + fieldlength = fieldlength < 0 ? 0 : fieldlength; if (x<inset || x>=width-inset || y<inset || y>=length-inset) { - return OUTSIDE; + return OUTSIDE; } /* @@ -399,18 +407,19 @@ TkpScrollbarPosition( */ if (y < scrollPtr->sliderFirst) { - return TOP_GAP; + return TOP_GAP; } if (y < scrollPtr->sliderLast) { - return SLIDER; + return SLIDER; } if (y < fieldlength){ - return BOTTOM_GAP; + return BOTTOM_GAP; } if (y < fieldlength + arrowSize) { - return TOP_ARROW; + return TOP_ARROW; } return BOTTOM_ARROW; + } /* @@ -458,7 +467,7 @@ UpdateControlValues( width = contrlRect.size.width; height = contrlRect.size.height; - variant = contrlRect.size.width < metrics[0].width ? 1 : 0; + variant = contrlRect.size.width < metrics[0].width ? 1 : 0; /* * Ensure we set scrollbar control bounds only once all size adjustments @@ -514,8 +523,8 @@ UpdateControlValues( * * ScrollbarPress -- * - * This procedure is invoked in response to <ButtonPress> events. - * Enters a modal loop to handle scrollbar interactions. + * This procedure is invoked in response to <ButtonPress>, <ButtonRelease>, + * <EnterNotify>, and <LeaveNotify> events. Scrollbar appearance is modified. * *-------------------------------------------------------------- */ @@ -526,6 +535,13 @@ ScrollbarPress(TkScrollbar *scrollPtr, XEvent *eventPtr) if (eventPtr->type == ButtonPress) { UpdateControlValues(scrollPtr); + info.trackInfo.scrollbar.pressState = 1; + } + if (eventPtr->type == EnterNotify) { + info.trackInfo.scrollbar.pressState = 1; + } + if (eventPtr->type == ButtonRelease || eventPtr->type == LeaveNotify) { + info.trackInfo.scrollbar.pressState = 0; } return TCL_OK; } @@ -566,6 +582,9 @@ ScrollbarEventProc( TkScrollbarEventuallyRedraw(scrollPtr); break; case ButtonPress: + case ButtonRelease: + case EnterNotify: + case LeaveNotify: ScrollbarPress(clientData, eventPtr); break; default: diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c index 39990e6..75473bf 100644 --- a/macosx/tkMacOSXWm.c +++ b/macosx/tkMacOSXWm.c @@ -2893,17 +2893,20 @@ WmProtocolCmd( } else { prevPtr->nextPtr = protPtr->nextPtr; } + if (protPtr->command) + ckfree(protPtr->command); Tcl_EventuallyFree(protPtr, TCL_DYNAMIC); break; } } cmd = Tcl_GetStringFromObj(objv[4], &cmdLength); if (cmdLength > 0) { - protPtr = ckalloc(HANDLER_SIZE(cmdLength)); + protPtr = ckalloc(sizeof(ProtocolHandler)); protPtr->protocol = protocol; protPtr->nextPtr = wmPtr->protPtr; wmPtr->protPtr = protPtr; protPtr->interp = interp; + protPtr->command = ckalloc(cmdLength+1); strcpy(protPtr->command, cmd); } return TCL_OK; diff --git a/macosx/tkMacOSXWm.h b/macosx/tkMacOSXWm.h index 0a128ef..e904f50 100644 --- a/macosx/tkMacOSXWm.h +++ b/macosx/tkMacOSXWm.h @@ -29,15 +29,13 @@ typedef struct ProtocolHandler { * same top-level window, or NULL for end of * list. */ Tcl_Interp *interp; /* Interpreter in which to invoke command. */ - char command[]; /* Tcl command to invoke when a client message + char* command; /* Tcl command to invoke when a client message * for this protocol arrives. The actual size * of the structure varies to accommodate the * needs of the actual command. THIS MUST BE * THE LAST FIELD OF THE STRUCTURE. */ } ProtocolHandler; -#define HANDLER_SIZE(cmdLength) \ -((unsigned) (sizeof(ProtocolHandler) + cmdLength + 1)) /* * A data structure of the following type holds window-manager-related diff --git a/macosx/tkMacOSXXStubs.c b/macosx/tkMacOSXXStubs.c index 2251b8f..004ac1b 100644 --- a/macosx/tkMacOSXXStubs.c +++ b/macosx/tkMacOSXXStubs.c @@ -882,16 +882,18 @@ XGetImage( int bitmap_pad = 0; int bytes_per_row = 4*width; int size; - MacDrawable *macDraw = (MacDrawable *) d; + MacDrawable *macDraw = (MacDrawable *) d; // Where is this variable used? May it be removed? + int scalefactor = 1; +#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 1070 NSWindow *win = TkMacOSXDrawableWindow(d); /* This code assumes that backing scale factors are integers. Currently * Retina displays use a scale factor of 2.0 and normal displays use 1.0. * We do not support any other values here. */ - int scalefactor = 1; if (win && [win respondsToSelector:@selector(backingScaleFactor)]) { scalefactor = ([win backingScaleFactor] == 2.0) ? 2 : 1; } +#endif int scaled_height = height * scalefactor; int scaled_width = width * scalefactor; |