From 11dbb8af58fd851913e5c781e3164e8211e93745 Mon Sep 17 00:00:00 2001 From: das Date: Mon, 23 Apr 2007 21:24:32 +0000 Subject: * macosx/tkMacOSXCarbonEvents.c: add window event target carbon event * macosx/tkMacOSXEvent.c: handler for all kEventClassWindow and * macosx/tkMacOSXEvent.h: kEventClassMouse events; * macosx/tkMacOSXNotify.c: move all remaining events except for * macosx/tkMacOSXWindowEvent.c: kEventClassKeyboard from dispatcher to application event handler; pass event handler callRef downstream; fix debug event tracing; process all tcl event types in carbon event timer; delay carbon event timer first fire; add TkMacOSXTrackingLoop() to mark enter/exit of event tracking loop during which all tcl events but only carbon update events should be processed by the timer (replaces various calls to Tcl_SetServiceMode()); rename TkMacOSXReceiveAndProcessEvent() to TkMacOSXReceiveAndDispatchEvent(), move it from tkMacOSXEvent.c to tkMacOSXCarbonEvents.c and modify it to dequeue only update events during a tracking loop; add TkMacOSXRunTclEventLoop() to standardize the various ways in use to run the tcl event loop; add handling of kEventClassAppearance events (for ScrollBarVariantChanged event). * macosx/tkMacOSXDialog.c: use new TkMacOSXTrackingLoop() around * macosx/tkMacOSXEvent.c: blocking API that puts up modal dialogs * macosx/tkMacOSXMenu.c: or when entering/exiting menu/control * macosx/tkMacOSXMouseEvent.c: tracking, window dragging and other * macosx/tkMacOSXScale.c: mouse tracking loops. * macosx/tkMacOSXScrlbr.c: * macosx/tkMacOSXWindowEvent.c: * macosx/tkMacOSXWm.c: * macosx/tkMacOSXDialog.c: use new TkMacOSXRunTclEventLoop() * macosx/tkMacOSXScale.c: instead of Tcl_DoOneEvent(), * macosx/tkMacOSXScrlbr.c: Tcl_ServiceAll(), TclServiceIdle() * macosx/tkMacOSXWindowEvent.c: and Tcl_GlobalEval("update idletasks"). * macosx/tkMacOSXColor.c: make available as Tk system colors all * macosx/tkMacOSXPort.h: appearance manager brushes, text colors and backgrounds with new and legacy names, as well as the fully transparent color "systemTransparent"; add TkMacOSXSetColorIn{Port,Context}() to directly set an X pixel color value in the current QD port resp. the given CG context without requiring passage through rgb representation (lossy for most system colors); modernize/remove Classic-era code; replace crufty strcmp() elseifs by Tcl_GetIndexFromObjStruct(). * macosx/tkMacOSXButton.c: use new TkMacOSXSetColorInPort() * macosx/tkMacOSXDraw.c: instead of setting rgb color directly * macosx/tkMacOSXMenubutton.c: to allow for non-rgb system colors. * macosx/tkMacOSXCursor.c: implement "none" cursor as on other platforms [Patch 1615427]; add all missing appearance manager cursors. * macosx/tkMacOSXDefault.h: set SELECT_FG_COLORs to None to match aqua L&F; use standard system color names; use new 'menu' system font; correct default scrollbar width. * macosx/tkMacOSXDraw.c: standardize initialization, use and * macosx/tkMacOSXInt.h: emptying of various static temp rgns * macosx/tkMacOSXRegion.c: onto two global RgnHandles; in debug * macosx/tkMacOSXSubwindows.c: builds, verify emptiness of these temp * macosx/tkMacOSXWindowEvent.c: rgns before use. * macosx/tkMacOSXDraw.c: add TkMacOSX{Setup,Restore}DrawingContext() to * macosx/tkMacOSXInt.h: abstract common setup & teardown of drawing environment (for both CG and QD); save/restore QD theme drawing state; handle GC clip region; add TkpClipDrawableToRect() to allow clipped drawing into drawable regardless of GC used; use new system color "systemWindowHeaderBackground" to setup background in themed toplevels; correct implementation of TkMacOSXMakeStippleMap(). * macosx/tkMacOSXEntry.c: use new TkMacOSXSetupDrawingContext() and * macosx/tkMacOSXFont.c: TkMacOSXRestoreDrawingContext() instead of * macosx/ttkMacOSXTheme.c: various setup/teardown procs like TkMacOSX{SetUp,Release}CGContext(), TkMacOSXQuarz{Start,End}Draw(), TkMacOSXSetUpGraphicsPort() etc. * macosx/tkMacOSXEmbed.c: add CG context and drawable clip rgn fields * macosx/tkMacOSXInt.h: to MacDrawable struct. * macosx/tkMacOSXSubwindows.c: * macosx/tkMacOSXDialog.c: make -parent option of tk_getOpenFile et al. use the sheet version of NavServices dialogs; ensure native parent win exists before using StandardSheet API for tk_messageBox [Bug 1677611]; force sheets to behave like app-modal dialogs via WindowModality() API; use more modern ColorPicker API. * macosx/tkAboutDlg.r: use themed movable modal dialog, fix (c) year. * macosx/tkMacOSXEntry.c: take xOff/yOff of MacDrawable into account * macosx/ttkMacOSXTheme.c: when computing locations/bounds to ensure correct posititioning when not drawing into intermediate pixmap. * macosx/tkMacOSXFont.c: use appearance manager API to map system font * macosx/tkMacOSXFont.h: names to TkFonts; add "menu" system font for menu item text drawing from MDEF; always draw with CG; remove QD dependent stippling algorithm; move most header declarations into the source file (as they were not used anywhere else). * macosx/tkMacOSXMenu.c: large-scale rewrite of custom * macosx/tkMacOSXMenu.r (removed): MDEF and related code that * macosx/Wish.xcode/project.pbxproj: restores many longtime-MIA * macosx/Wish.xcodeproj/project.pbxproj: features to working order * unix/Makefile.in: (e.g. images, custom colors & fonts in menus etc); implement compound menu items; use Appearance Mgr and ThemeText APIs to mimic native MDEF as closely as possible when default "menu" system font is used; remove now obsolete SICN drawing code and resources. * macosx/tkMacOSXCarbonEvents.c: handle additional menu carbon events * macosx/tkMacOSXEvent.c: in order to support <> in * macosx/tkMacOSXMenu.c: the menubar and in menus that are not * macosx/tkMacOSXMenus.c: using the custom MDEF [Bug 1620826]; fix early and missing clearing of current Tk active menu entry; fix extraneous sending of <> during active menu entry clearing. * macosx/tkMacOSXMouseEvent.c: add support for async window dragging by the window server; set the corresponding window attribute by default. * macosx/tkMacOSXMouseEvent.c: rationalized handling order of non-mousedown events; add TkMacOSXModifierState() to retrieve the current key modifiers in carbon format. * macosx/tkMacOSXScrlbr.c: use appearance manager API to retrieve scrollbar component metrics; add awareness of multiple possibilites for scrollbar arrow position in aqua and handle user changes to arrow position pref; handle difference in metrics of small & large scrollbar variants; handle aqua "jump to here" scrollbar behaviour; correct computation of scroll view size and position; enforce min scrollbar height to avoid scrollbar component overlap; erase scrollbar area outside of standard width; remove broken auto-adjust code; account for window class when leaving space for grow box; remove code to manually draw grow box; use modern API for thumb scroll proc; replace HiliteControl() by modern API; replace control mgr constants with appearance mgr equivalents. * macosx/tkMacOSXSubwindows.c: use SetWindowBounds() API instead of SizeWindow(); invalidate clip regions after X{Map,Unmap}Window as fix for [Bug 940117] made them dependent on mapping state; remove unneeded calls to TkMacOSXInvalClipRgns() and unnecessary setting of QD port; use native-endian pixmap on intel; remove obsolete pixmap pix locking. * macosx/tkMacOSXWindowEvent.c: handle only the first of a batch of kEventAppAvailableWindowBoundsChanged events sent per transaction; handle kEventWindowBoundsChanged event to support live window resizing and centralized sending of location/size changed ConfigureNotify events; ensure HIGrowBox is redrawn after bounds change; constrain window after dragging to ensure titlebar is not inacessible offscreen or under dock/menubar; handle kEventWindowGetRegion and kEventWindowDrawContent for transparent windows to mark resp. paint content region as transparent; handle kEventWindowConstrain for fullscreen windows to ensure bounds match new screen size; enter/exit fullscreen UIMode upon activation/deactivation of fullscreen window. * macosx/tkMacOSXWm.c: use live-resize and async-drag carbon window * macosx/tkMacOSXWm.h: attributes for toplevels by default; implement new [wm attributes] -topmost, -transparent and -fullscreen; refactor WmAttributesCmd() parallelling the tkUnixWm.c implementation, use thus factored proc to set proxy icon from [wm iconbitmap]; dynamically determine default values for toplevel min and max sizes (similar to tkWinWm.c impl): min sizes depend on window class & attributes to ensure visibility of all titlebar widgets and grow box, max sizes depend on maximal window bounds for all active displays; factor out code that puts into effect changes to master or override_redirect; use RepositionWindow() API to determine staggered initial window bounds; correct resize limit calculations, handle gridding and use modern resize API in TkMacOSXGrowToplevel(); remove sending of ConfigureNotify after resize or zoom (now handled by BoundsChanged handler); correct composite carbon window attribute handling, remove currently unusable attributes and add new attributes in [tk::unsupported::MacWindowStyle]; ensure validity of window class and attributes before use; apply changes to window class when handling carbon window attribute changes (if HIWindowChangeClass() API available); add debug build warning message when deprecated window style is used instead of window class; use transparent HIGrowBox for resizable windows; avoid unnecessary calls to window structure width API; use tcl time API in TkpGetMS(); add TkMacOSXEnterExitFullscreen() to enter/exit UIMode with dock and menubar hidden; restrict wmTracing output to debug builds; remove unneeded calls to TkMacOSXInvalClipRgns() and unnecessary setting of QD port; workaround GetWindowStructureWidths() Carbon bug (bogus results for never-mapped floating windows). * macosx/tkMacOSXXStubs.c (TkMacOSXDisplayChanged): add maximal window bounds field to Screen record (in ext_data), computed as the union of available window positioning bounds of all graphics devices (displays). * macosx/tkMacOSXBitmap.c: fix macRoman encoding leak. * macosx/tkMacOSXCursor.c: * macosx/tkMacOSXDebug.c (TkMacOSXCarbonEventToAscii): use static * macosx/tkMacOSXDebug.h: buffer to simplify callers; const fixes. * macosx/tkMacOSXBitmap.c: use more efficient QDSwapPort() instead of * macosx/tkMacOSXButton.c: GetPort()/SetPort()/GetGWorld()/SetGWorld(). * macosx/tkMacOSXDraw.c: * macosx/tkMacOSXMenubutton.c: * macosx/tkMacOSXScale.c: * macosx/tkMacOSXScrlbr.c: * macosx/tkMacOSXXStubs.c: * macosx/tkMacOSXColor.c: use kHIToolboxVersionNumber for runtime OS * macosx/tkMacOSXEntry.c: version check rather than Gestalt() etc. * macosx/tkMacOSXInt.h: * macosx/tkMacOSXWm.c: * macosx/tkMacOSXDraw.c: remove obsolete and now incorrect * macosx/tkMacOSXInt.h: tkMenuCascadeRgn clipping code. * macosx/tkMacOSXMenu.c: * macosx/tkMacOSXHLEvents.c: replace Tcl_GlobalEval() resp. Tcl_Eval() * macosx/tkMacOSXScrlbr.c: by Tcl_EvalEx(). * macosx/tkMacOSXInit.c: * macosx/tkMacOSXInit.c (TkpInit): reorder initialization steps. * macosx/tkMacOSXKeyEvent.c: remove pre-10.2 support. * macosx/tkMacOSXMenus.c: remove now useless call to TkMacOSXHandleTearoffMenu(); use \x.. quoting for non-latin1 macroman literar chars to allow file to be edited as utf-8. * macosx/tkMacOSXScale.c: replace TrackControl() by modern * macosx/tkMacOSXScrlbr.c: HandleControlClick() API (using new TkMacOSXModifierState()). * macosx/tkMacOSXInt.h: move all constant #defines needed to * macosx/tkMacOSXColor.c: support building on older OS X releases * macosx/tkMacOSXEvent.h: to a central location in tkMacOSXInt.h. * macosx/tkMacOSXFont.c: * macosx/tkMacOSXMenu.c: * macosx/tkMacOSXMenubutton.c: * macosx/tkMacOSXMenus.c: * macosx/tkMacOSXMouseEvent.c: * macosx/tkMacOSXWm.c: * macosx/ttkMacOSXTheme.c: * macosx/tkMacOSXInt.h: add ChkErr() macro to factor out * macosx/tkMacOSXButton.c: Carbon OSStatus return value checking * macosx/tkMacOSXCarbonEvents.c: and TkMacOSXDbgMsg() macro to factour * macosx/tkMacOSXClipboard.c: out debug message output; use these * macosx/tkMacOSXColor.c: macros to replace #ifdef TK_MAC_DEBUG * macosx/tkMacOSXCursor.c: blocks & direct printing to stderr, * macosx/tkMacOSXDebug.c: and to do additional OSStatus return * macosx/tkMacOSXDialog.c: checking, and to standardize OSStatus * macosx/tkMacOSXDraw.c: usage. * macosx/tkMacOSXEntry.c: * macosx/tkMacOSXEvent.c: * macosx/tkMacOSXFont.c: * macosx/tkMacOSXHLEvents.c: * macosx/tkMacOSXInit.c: * macosx/tkMacOSXKeyEvent.c: * macosx/tkMacOSXMenu.c: * macosx/tkMacOSXMenubutton.c: * macosx/tkMacOSXMenus.c: * macosx/tkMacOSXMouseEvent.c: * macosx/tkMacOSXScrlbr.c: * macosx/tkMacOSXSubwindows.c: * macosx/tkMacOSXWindowEvent.c: * macosx/tkMacOSXWm.c: * macosx/tkMacOSXXStubs.c: * macosx/tkMacOSXSend.c: remove duplicate/unused declarations * macosx/tkMacOSXXStubs.c: * macosx/tkMacOSXDebug.c: const fixes. * macosx/tkMacOSXInit.c: * macosx/tkMacOSXTest.c: * macosx/tkMacOSXWm.c: * macosx/tkMacOSXXStubs.c: * macosx/Wish-Info.plist.in: add tcl document extensions/mime types and LSMinimumSystemVersion, LSRequiresCarbon & NSAppleScriptEnabled keys. * macosx/Wish-Common.xcconfig: add Wish's Info.plist as __info_plist section to tktest; enable more warnings. * macosx/Wish.xcodeproj/project.pbxproj: add 'DebugMemCompile' build configuration that calls configure with --enable-symbols=all; disable configure check for __attribute__((__visibility__("hidden"))) in Debug configuration to restore availability of ZeroLink. * macosx/Wish-Common.xcconfig: fix whitespace. * macosx/Wish-Debug.xcconfig: * macosx/Wish-Release.xcconfig: * macosx/tkMacOSXAETE.r: * macosx/tkMacOSXConfig.c: * macosx/tkMacOSXCursors.r: * macosx/tkMacOSXKeyboard.c: * macosx/tkMacOSXSend.c: * macosx/ttkMacOSXTheme.c: * macosx/tkMacOSXXCursors.r: * macosx/README: * macosx/GNUmakefile: fix/add copyright and license refs. * macosx/Tk-Info.plist.in: * macosx/Wish-Info.plist.in: * macosx/Wish.xcode/project.pbxproj: * macosx/Wish.xcodeproj/project.pbxproj: * macosx/tkMacOSX.h: --- ChangeLog | 340 ++- changes | 56 +- macosx/GNUmakefile | 23 +- macosx/README | 18 +- macosx/Tk-Info.plist.in | 17 +- macosx/Wish-Common.xcconfig | 8 +- macosx/Wish-Debug.xcconfig | 4 +- macosx/Wish-Info.plist.in | 29 +- macosx/Wish-Release.xcconfig | 4 +- macosx/Wish.xcode/project.pbxproj | 17 +- macosx/Wish.xcodeproj/project.pbxproj | 33 +- macosx/tkAboutDlg.r | 34 +- macosx/tkMacOSX.h | 13 +- macosx/tkMacOSXAETE.r | 17 +- macosx/tkMacOSXBitmap.c | 277 +- macosx/tkMacOSXButton.c | 1898 ++++++------ macosx/tkMacOSXCarbonEvents.c | 649 +++-- macosx/tkMacOSXClipboard.c | 331 ++- macosx/tkMacOSXColor.c | 919 +++--- macosx/tkMacOSXConfig.c | 26 +- macosx/tkMacOSXCursor.c | 467 +-- macosx/tkMacOSXCursors.r | 32 +- macosx/tkMacOSXDebug.c | 303 +- macosx/tkMacOSXDebug.h | 93 +- macosx/tkMacOSXDefault.h | 64 +- macosx/tkMacOSXDialog.c | 1444 +++++---- macosx/tkMacOSXDraw.c | 1508 +++++----- macosx/tkMacOSXEmbed.c | 1068 ++++--- macosx/tkMacOSXEntry.c | 328 +-- macosx/tkMacOSXEvent.c | 300 +- macosx/tkMacOSXEvent.h | 125 +- macosx/tkMacOSXFont.c | 2520 +++++++--------- macosx/tkMacOSXFont.h | 104 +- macosx/tkMacOSXHLEvents.c | 511 ++-- macosx/tkMacOSXInit.c | 366 +-- macosx/tkMacOSXInt.h | 239 +- macosx/tkMacOSXKeyEvent.c | 1359 ++++----- macosx/tkMacOSXKeyboard.c | 691 ++--- macosx/tkMacOSXMenu.c | 5142 ++++++++++++++++----------------- macosx/tkMacOSXMenu.r | 47 - macosx/tkMacOSXMenubutton.c | 970 +++---- macosx/tkMacOSXMenus.c | 250 +- macosx/tkMacOSXMouseEvent.c | 660 +++-- macosx/tkMacOSXNotify.c | 79 +- macosx/tkMacOSXPort.h | 45 +- macosx/tkMacOSXRegion.c | 135 +- macosx/tkMacOSXScale.c | 277 +- macosx/tkMacOSXScrlbr.c | 1253 ++++---- macosx/tkMacOSXSend.c | 191 +- macosx/tkMacOSXSubwindows.c | 642 ++-- macosx/tkMacOSXTest.c | 13 +- macosx/tkMacOSXWindowEvent.c | 766 +++-- macosx/tkMacOSXWm.c | 4556 +++++++++++++++-------------- macosx/tkMacOSXWm.h | 168 +- macosx/tkMacOSXXCursors.r | 195 +- macosx/tkMacOSXXStubs.c | 337 ++- macosx/ttkMacOSXTheme.c | 303 +- unix/Makefile.in | 4 +- 58 files changed, 16458 insertions(+), 15810 deletions(-) delete mode 100644 macosx/tkMacOSXMenu.r diff --git a/ChangeLog b/ChangeLog index 1af6750..d18f36a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,345 @@ -2007-04-21 Jeff Hobbs +2007-04-23 Daniel Steffen *** 8.5a6 TAGGED FOR RELEASE *** + * generic/tkCanvas.c: allow -selectforeground option to be None; add + * generic/tkCanvText.c: fallback to fgColor when selFgColor is None + * generic/tkEntry.c: (new default on aqua to match native L&F). + * generic/tkListbox.c: + * generic/tkText.c: + + * generic/tkCanvas.c: add support for bypassing all of Tk's double + * generic/tkEntry.c: buffered drawing into intermediate pixmaps + * generic/tkFrame.c: (via TK_NO_DOUBLE_BUFFERING #define), it is + * generic/tkListbox.c: unnecessary & wasteful on aqua where all + * generic/tkPanedWindow.c: drawing is already double-buffered by the + * generic/tkTextDisp.c: window server. (Use of this on other + * generic/ttk/ttkWidget.c: platforms would only require implementation + * unix/tkUnixScale.c: of TkpClipDrawableToRect()). + * macosx/tkMacOSXPort.h: + + * library/bgerror.tcl: on aqua, use moveable alert resp. modal dialog + * library/dialog.tcl: window class and corresponding system + background pattern; fix button padding. + + * library/tearoff.tcl: correct aqua menu bar height; vertically offset + * library/tk.tcl: aqua tearoff floating window to match menu. + + * library/demos/goldberg.tcl: fix overwriting of widget demo global. + + * library/demos/menu.tcl: on aqua, use custom MDEF and tearoffs; + * library/demos/menubu.tcl: correct menubutton toplevel name. + + * library/demos/puzzle.tcl: fix button size & padding for aqua. + * library/demos/radio.tcl: + + * macosx/tkMacOSXCarbonEvents.c: add window event target carbon event + * macosx/tkMacOSXEvent.c: handler for all kEventClassWindow and + * macosx/tkMacOSXEvent.h: kEventClassMouse events; + * macosx/tkMacOSXNotify.c: move all remaining events except for + * macosx/tkMacOSXWindowEvent.c: kEventClassKeyboard from dispatcher to + application event handler; pass event handler callRef downstream; fix + debug event tracing; process all tcl event types in carbon event timer; + delay carbon event timer first fire; add TkMacOSXTrackingLoop() to mark + enter/exit of event tracking loop during which all tcl events but only + carbon update events should be processed by the timer (replaces various + calls to Tcl_SetServiceMode()); rename TkMacOSXReceiveAndProcessEvent() + to TkMacOSXReceiveAndDispatchEvent(), move it from tkMacOSXEvent.c to + tkMacOSXCarbonEvents.c and modify it to dequeue only update events + during a tracking loop; add TkMacOSXRunTclEventLoop() to standardize + the various ways in use to run the tcl event loop; add handling of + kEventClassAppearance events (for ScrollBarVariantChanged event). + + * macosx/tkMacOSXDialog.c: use new TkMacOSXTrackingLoop() around + * macosx/tkMacOSXEvent.c: blocking API that puts up modal dialogs + * macosx/tkMacOSXMenu.c: or when entering/exiting menu/control + * macosx/tkMacOSXMouseEvent.c: tracking, window dragging and other + * macosx/tkMacOSXScale.c: mouse tracking loops. + * macosx/tkMacOSXScrlbr.c: + * macosx/tkMacOSXWindowEvent.c: + * macosx/tkMacOSXWm.c: + + * macosx/tkMacOSXDialog.c: use new TkMacOSXRunTclEventLoop() + * macosx/tkMacOSXScale.c: instead of Tcl_DoOneEvent(), + * macosx/tkMacOSXScrlbr.c: Tcl_ServiceAll(), TclServiceIdle() + * macosx/tkMacOSXWindowEvent.c: and Tcl_GlobalEval("update idletasks"). + + * macosx/tkMacOSXColor.c: make available as Tk system colors all + * macosx/tkMacOSXPort.h: appearance manager brushes, text colors and + backgrounds with new and legacy names, as well as the fully transparent + color "systemTransparent"; add TkMacOSXSetColorIn{Port,Context}() to + directly set an X pixel color value in the current QD port resp. the + given CG context without requiring passage through rgb representation + (lossy for most system colors); modernize/remove Classic-era code; + replace crufty strcmp() elseifs by Tcl_GetIndexFromObjStruct(). + + * macosx/tkMacOSXButton.c: use new TkMacOSXSetColorInPort() + * macosx/tkMacOSXDraw.c: instead of setting rgb color directly + * macosx/tkMacOSXMenubutton.c: to allow for non-rgb system colors. + + * macosx/tkMacOSXCursor.c: implement "none" cursor as on other + platforms [Patch 1615427]; add all missing appearance manager cursors. + + * macosx/tkMacOSXDefault.h: set SELECT_FG_COLORs to None to match aqua + L&F; use standard system color names; use new 'menu' system font; + correct default scrollbar width. + + * macosx/tkMacOSXDraw.c: standardize initialization, use and + * macosx/tkMacOSXInt.h: emptying of various static temp rgns + * macosx/tkMacOSXRegion.c: onto two global RgnHandles; in debug + * macosx/tkMacOSXSubwindows.c: builds, verify emptiness of these temp + * macosx/tkMacOSXWindowEvent.c: rgns before use. + + * macosx/tkMacOSXDraw.c: add TkMacOSX{Setup,Restore}DrawingContext() to + * macosx/tkMacOSXInt.h: abstract common setup & teardown of drawing + environment (for both CG and QD); save/restore QD theme drawing state; + handle GC clip region; add TkpClipDrawableToRect() to allow clipped + drawing into drawable regardless of GC used; use new system color + "systemWindowHeaderBackground" to setup background in themed toplevels; + correct implementation of TkMacOSXMakeStippleMap(). + + * macosx/tkMacOSXEntry.c: use new TkMacOSXSetupDrawingContext() and + * macosx/tkMacOSXFont.c: TkMacOSXRestoreDrawingContext() instead of + * macosx/ttkMacOSXTheme.c: various setup/teardown procs like + TkMacOSX{SetUp,Release}CGContext(), TkMacOSXQuarz{Start,End}Draw(), + TkMacOSXSetUpGraphicsPort() etc. + + * macosx/tkMacOSXEmbed.c: add CG context and drawable clip rgn fields + * macosx/tkMacOSXInt.h: to MacDrawable struct. + * macosx/tkMacOSXSubwindows.c: + + * macosx/tkMacOSXDialog.c: make -parent option of tk_getOpenFile et al. + use the sheet version of NavServices dialogs; ensure native parent win + exists before using StandardSheet API for tk_messageBox [Bug 1677611]; + force sheets to behave like app-modal dialogs via WindowModality() API; + use more modern ColorPicker API. + + * macosx/tkAboutDlg.r: use themed movable modal dialog, fix (c) year. + + * macosx/tkMacOSXEntry.c: take xOff/yOff of MacDrawable into account + * macosx/ttkMacOSXTheme.c: when computing locations/bounds to ensure + correct posititioning when not drawing into intermediate pixmap. + + * macosx/tkMacOSXFont.c: use appearance manager API to map system font + * macosx/tkMacOSXFont.h: names to TkFonts; add "menu" system font for + menu item text drawing from MDEF; always draw with CG; remove QD + dependent stippling algorithm; move most header declarations into the + source file (as they were not used anywhere else). + + * macosx/tkMacOSXMenu.c: large-scale rewrite of custom + * macosx/tkMacOSXMenu.r (removed): MDEF and related code that + * macosx/Wish.xcode/project.pbxproj: restores many longtime-MIA + * macosx/Wish.xcodeproj/project.pbxproj: features to working order + * unix/Makefile.in: (e.g. images, custom colors & + fonts in menus etc); implement compound menu items; use Appearance Mgr + and ThemeText APIs to mimic native MDEF as closely as possible when + default "menu" system font is used; remove now obsolete SICN drawing + code and resources. + + * macosx/tkMacOSXCarbonEvents.c: handle additional menu carbon events + * macosx/tkMacOSXEvent.c: in order to support <> in + * macosx/tkMacOSXMenu.c: the menubar and in menus that are not + * macosx/tkMacOSXMenus.c: using the custom MDEF [Bug 1620826]; + fix early and missing clearing of current Tk active menu entry; fix + extraneous sending of <> during active menu entry clearing. + + * macosx/tkMacOSXMouseEvent.c: add support for async window dragging by + the window server; set the corresponding window attribute by default. + + * macosx/tkMacOSXMouseEvent.c: rationalized handling order of + non-mousedown events; add TkMacOSXModifierState() to retrieve the + current key modifiers in carbon format. + + * macosx/tkMacOSXScrlbr.c: use appearance manager API to retrieve + scrollbar component metrics; add awareness of multiple possibilites for + scrollbar arrow position in aqua and handle user changes to arrow + position pref; handle difference in metrics of small & large scrollbar + variants; handle aqua "jump to here" scrollbar behaviour; correct + computation of scroll view size and position; enforce min scrollbar + height to avoid scrollbar component overlap; erase scrollbar area + outside of standard width; remove broken auto-adjust code; account for + window class when leaving space for grow box; remove code to manually + draw grow box; use modern API for thumb scroll proc; replace + HiliteControl() by modern API; replace control mgr constants with + appearance mgr equivalents. + + * macosx/tkMacOSXSubwindows.c: use SetWindowBounds() API instead of + SizeWindow(); invalidate clip regions after X{Map,Unmap}Window as fix + for [Bug 940117] made them dependent on mapping state; remove unneeded + calls to TkMacOSXInvalClipRgns() and unnecessary setting of QD port; + use native-endian pixmap on intel; remove obsolete pixmap pix locking. + + * macosx/tkMacOSXWindowEvent.c: handle only the first of a batch of + kEventAppAvailableWindowBoundsChanged events sent per transaction; + handle kEventWindowBoundsChanged event to support live window resizing + and centralized sending of location/size changed ConfigureNotify + events; ensure HIGrowBox is redrawn after bounds change; constrain + window after dragging to ensure titlebar is not inacessible + offscreen or under dock/menubar; handle kEventWindowGetRegion and + kEventWindowDrawContent for transparent windows to mark resp. paint + content region as transparent; handle kEventWindowConstrain for + fullscreen windows to ensure bounds match new screen size; enter/exit + fullscreen UIMode upon activation/deactivation of fullscreen window. + + * macosx/tkMacOSXWm.c: use live-resize and async-drag carbon window + * macosx/tkMacOSXWm.h: attributes for toplevels by default; implement + new [wm attributes] -topmost, -transparent and -fullscreen; refactor + WmAttributesCmd() parallelling the tkUnixWm.c implementation, use thus + factored proc to set proxy icon from [wm iconbitmap]; dynamically + determine default values for toplevel min and max sizes (similar to + tkWinWm.c impl): min sizes depend on window class & attributes to + ensure visibility of all titlebar widgets and grow box, max sizes + depend on maximal window bounds for all active displays; factor out + code that puts into effect changes to master or override_redirect; use + RepositionWindow() API to determine staggered initial window bounds; + correct resize limit calculations, handle gridding and use modern + resize API in TkMacOSXGrowToplevel(); remove sending of ConfigureNotify + after resize or zoom (now handled by BoundsChanged handler); correct + composite carbon window attribute handling, remove currently unusable + attributes and add new attributes in [tk::unsupported::MacWindowStyle]; + ensure validity of window class and attributes before use; apply + changes to window class when handling carbon window attribute changes + (if HIWindowChangeClass() API available); add debug build warning + message when deprecated window style is used instead of window class; + use transparent HIGrowBox for resizable windows; avoid unnecessary + calls to window structure width API; use tcl time API in TkpGetMS(); + add TkMacOSXEnterExitFullscreen() to enter/exit UIMode with dock and + menubar hidden; restrict wmTracing output to debug builds; remove + unneeded calls to TkMacOSXInvalClipRgns() and unnecessary setting of QD + port; workaround GetWindowStructureWidths() Carbon bug (bogus results + for never-mapped floating windows). + + * macosx/tkMacOSXXStubs.c (TkMacOSXDisplayChanged): add maximal window + bounds field to Screen record (in ext_data), computed as the union of + available window positioning bounds of all graphics devices (displays). + + * macosx/tkMacOSXBitmap.c: fix macRoman encoding leak. + * macosx/tkMacOSXCursor.c: + + * macosx/tkMacOSXDebug.c (TkMacOSXCarbonEventToAscii): use static + * macosx/tkMacOSXDebug.h: buffer to simplify callers; const fixes. + + * macosx/tkMacOSXBitmap.c: use more efficient QDSwapPort() instead of + * macosx/tkMacOSXButton.c: GetPort()/SetPort()/GetGWorld()/SetGWorld(). + * macosx/tkMacOSXDraw.c: + * macosx/tkMacOSXMenubutton.c: + * macosx/tkMacOSXScale.c: + * macosx/tkMacOSXScrlbr.c: + * macosx/tkMacOSXXStubs.c: + + * macosx/tkMacOSXColor.c: use kHIToolboxVersionNumber for runtime OS + * macosx/tkMacOSXEntry.c: version check rather than Gestalt() etc. + * macosx/tkMacOSXInt.h: + * macosx/tkMacOSXWm.c: + + * macosx/tkMacOSXDraw.c: remove obsolete and now incorrect + * macosx/tkMacOSXInt.h: tkMenuCascadeRgn clipping code. + * macosx/tkMacOSXMenu.c: + + * macosx/tkMacOSXHLEvents.c: replace Tcl_GlobalEval() resp. Tcl_Eval() + * macosx/tkMacOSXScrlbr.c: by Tcl_EvalEx(). + * macosx/tkMacOSXInit.c: + + * macosx/tkMacOSXInit.c (TkpInit): reorder initialization steps. + + * macosx/tkMacOSXKeyEvent.c: remove pre-10.2 support. + + * macosx/tkMacOSXMenus.c: remove now useless call to + TkMacOSXHandleTearoffMenu(); use \x.. quoting for non-latin1 macroman + literar chars to allow file to be edited as utf-8. + + * macosx/tkMacOSXScale.c: replace TrackControl() by modern + * macosx/tkMacOSXScrlbr.c: HandleControlClick() API (using new + TkMacOSXModifierState()). + + * macosx/tkMacOSXInt.h: move all constant #defines needed to + * macosx/tkMacOSXColor.c: support building on older OS X releases + * macosx/tkMacOSXEvent.h: to a central location in tkMacOSXInt.h. + * macosx/tkMacOSXFont.c: + * macosx/tkMacOSXMenu.c: + * macosx/tkMacOSXMenubutton.c: + * macosx/tkMacOSXMenus.c: + * macosx/tkMacOSXMouseEvent.c: + * macosx/tkMacOSXWm.c: + * macosx/ttkMacOSXTheme.c: + + * macosx/tkMacOSXInt.h: add ChkErr() macro to factor out + * macosx/tkMacOSXButton.c: Carbon OSStatus return value checking + * macosx/tkMacOSXCarbonEvents.c: and TkMacOSXDbgMsg() macro to factour + * macosx/tkMacOSXClipboard.c: out debug message output; use these + * macosx/tkMacOSXColor.c: macros to replace #ifdef TK_MAC_DEBUG + * macosx/tkMacOSXCursor.c: blocks & direct printing to stderr, + * macosx/tkMacOSXDebug.c: and to do additional OSStatus return + * macosx/tkMacOSXDialog.c: checking, and to standardize OSStatus + * macosx/tkMacOSXDraw.c: usage. + * macosx/tkMacOSXEntry.c: + * macosx/tkMacOSXEvent.c: + * macosx/tkMacOSXFont.c: + * macosx/tkMacOSXHLEvents.c: + * macosx/tkMacOSXInit.c: + * macosx/tkMacOSXKeyEvent.c: + * macosx/tkMacOSXMenu.c: + * macosx/tkMacOSXMenubutton.c: + * macosx/tkMacOSXMenus.c: + * macosx/tkMacOSXMouseEvent.c: + * macosx/tkMacOSXScrlbr.c: + * macosx/tkMacOSXSubwindows.c: + * macosx/tkMacOSXWindowEvent.c: + * macosx/tkMacOSXWm.c: + * macosx/tkMacOSXXStubs.c: + + * macosx/tkMacOSXSend.c: remove duplicate/unused declarations + * macosx/tkMacOSXXStubs.c: + + * macosx/tkMacOSXDebug.c: const fixes. + * macosx/tkMacOSXInit.c: + * macosx/tkMacOSXTest.c: + * macosx/tkMacOSXWm.c: + * macosx/tkMacOSXXStubs.c: + + * macosx/Wish-Info.plist.in: add tcl document extensions/mime types and + LSMinimumSystemVersion, LSRequiresCarbon & NSAppleScriptEnabled keys. + + * macosx/Wish-Common.xcconfig: add Wish's Info.plist as __info_plist + section to tktest; enable more warnings. + + * macosx/Wish.xcodeproj/project.pbxproj: add 'DebugMemCompile' build + configuration that calls configure with --enable-symbols=all; disable + configure check for __attribute__((__visibility__("hidden"))) in Debug + configuration to restore availability of ZeroLink. + + * macosx/Wish-Common.xcconfig: fix whitespace. + * macosx/Wish-Debug.xcconfig: + * macosx/Wish-Release.xcconfig: + * macosx/tkMacOSXAETE.r: + * macosx/tkMacOSXConfig.c: + * macosx/tkMacOSXCursors.r: + * macosx/tkMacOSXKeyboard.c: + * macosx/tkMacOSXSend.c: + * macosx/ttkMacOSXTheme.c: + * macosx/tkMacOSXXCursors.r: + * macosx/README: + + * macosx/GNUmakefile: fix/add copyright and license refs. + * macosx/Tk-Info.plist.in: + * macosx/Wish-Info.plist.in: + * macosx/Wish.xcode/project.pbxproj: + * macosx/Wish.xcodeproj/project.pbxproj: + * macosx/tkMacOSX.h: + + * unix/configure.in: install license.terms into Tk.framework; fix tk + debug build detection. + * unix/configure: autoconf-2.59 + + * doc/colors.n: document new Mac OS X system colors. + * doc/cursors.n: document new Mac OS X native cursors. + * doc/font.n: document new Mac OS X 'menu' system font. + * doc/wm.n: document new Mac OS X [wm attributes]. + * doc/ttk_image.n: fix 'make html' warning. + * doc/canvas.n: fix nroff typo. + +2007-04-21 Jeff Hobbs + * macosx/tkMacOSXBitmap.c, macosx/tkMacOSXButton.c: * macosx/tkMacOSXCarbonEvents.c, macosx/tkMacOSXClipboard.c: * macosx/tkMacOSXCursor.c, macosx/tkMacOSXDialog.c: diff --git a/changes b/changes index f78c017..66561fe 100644 --- a/changes +++ b/changes @@ -2,7 +2,7 @@ This file summarizes all changes made to Tk since version 1.0 was released on March 13, 1991. Changes that aren't backward compatible are marked specially. -RCS: @(#) $Id: changes,v 1.104 2007/04/22 07:04:41 hobbs Exp $ +RCS: @(#) $Id: changes,v 1.105 2007/04/23 21:24:32 das Exp $ 3/16/91 (bug fix) Modified tkWindow.c to remove Tk's Tcl commands from the interpreter when the main window is deleted (otherwise there will @@ -6251,7 +6251,7 @@ ttk::radiobutton, ttk::checkbutton, ttk::treeview, ttk::separator, ttk::scrollbar, ttk::entry, ttk::frame and ttk::labelframe widgets. Adds ttk::style command. -2006-11-02 (enhancement) Improve OS X Carbon event handling +2006-11-02 (enhancement) Improve OS X Carbon event handling. 2006-11-07 (configure change) Unix --enable-xft is enabled by default now. @@ -6262,7 +6262,7 @@ control display of console. 2006-11-30 (bug fix) Fix handling of Escape binding on OS X dialogs. -2006-12-01 (new feature) add -transparentcolor wm attribute on Windows. +2006-12-01 (new feature) Add -transparentcolor wm attribute on Windows. 2006-12-02 (new feature)[TIP 300] Added [font actual $font $char]. @@ -6271,11 +6271,55 @@ control display of console. 2006-12-11 (enhancement) Improved EWMH support for _NET_WM_PID and _NET_WM_PING. -2007-01-19 (configure change) ensre CPPFLAGS env var is used when set. +2007-01-19 (configure change) Ensure CPPFLAGS env var is used when set. -2007-02-19 (configure change) use SHLIB_SUFFIX=".so" on HP-UX IA64 (was +2007-02-19 (configure change) Use SHLIB_SUFFIX=".so" on HP-UX IA64 (was ".sl"). -2007-04-10 (platform support) correctly handling theming on Vista/Aero. +2007-04-10 (platform support) Correctly handle theming on Vista/Aero. + +2007-04-23 (enhancement) Allow empty value for -selectforeground option. + +2007-04-23 (platform support) Aqua: remove Tk-internal double buffering that is +wasteful on Aqua; allows direct-to-window CoreGraphics drawing (e.g. adding +support for colors with alpha). + +2007-04-23 (platform support) Aqua: add all OS theme colors/brushes (patterns) +as system colors. + +2007-04-23 (platform support) Aqua: use OS theme for tk_dialog and bgerror. + +2007-04-23 (platform support) Aqua: add 'none' cursor. + +2007-04-23 (platform support) Aqua: [tk_getOpenFile -parent] uses sheet dialog. + +2007-04-23 (bug fix) Aqua: fix custom MDEF and tearoff menu display. + +2007-04-23 (bug fix)[1620826] Aqua: fix <> support. + +2007-04-23 (platform support) Aqua: add support for live window resizing and +asynchronous window dragging; prevent window from becoming inacessible +offscreen or under Dock after dragging; use transparent grow box. + +2007-04-23 (platform support) Aqua: improve event processing during nested +event loops (e.g. modal dialogs, menu tracking, window resizing etc). + +2007-04-23 (bug fix) Aqua: add support for all possible aqua scrollbar arrow +positions, scrollbar variants and for "jump to here" scrollbar behaviour; +correct scroll view size computation; enforce minimal scrollbar height. + +2007-04-23 (platform support) Aqua: add [wm attributes] -topmost, -fullscreen +and -transparent (allows fully transparent window via -bg "systemTransparent"). + +2007-04-23 (platform support) Aqua: determine win min/max sizes dynamically; +correct size handling of gridded windows; improve computation of initial +window bounds; correct window size handling on multi-headed systems. + +2007-04-23 (platform support) Aqua: correct composite attribute handling in +[tk::unsupported::MacWindowStyle] and add new attributes; allow changing +window class of already existing windows. + +2007-04-23 (platform support) Aqua: add tcl document extensions and mime type +to Wish.app's Info.plist. --- Released 8.5a6, April 25, 2007 --- See ChangeLog for details --- diff --git a/macosx/GNUmakefile b/macosx/GNUmakefile index 3e2e286..8514f71 100644 --- a/macosx/GNUmakefile +++ b/macosx/GNUmakefile @@ -4,7 +4,12 @@ # uses the standard unix build system in tk/unix (which can be used directly instead of this # if you are not using the tk/macosx projects). # -# RCS: @(#) $Id: GNUmakefile,v 1.7 2006/10/16 17:36:18 das Exp $ +# Copyright (c) 2002-2007 Daniel A. Steffen +# +# See the file "license.terms" for information on usage and redistribution of +# this file, and for a DISCLAIMER OF ALL WARRANTIES. +# +# RCS: @(#) $Id: GNUmakefile,v 1.8 2007/04/23 21:24:32 das Exp $ # ######################################################################################################## @@ -18,8 +23,8 @@ BUILD_DIR ?= ${CURDIR}/../../build SYMROOT ?= ${BUILD_DIR}/${PROJECT} OBJROOT ?= ${SYMROOT} -EXTRA_CONFIGURE_ARGS ?= -EXTRA_MAKE_ARGS ?= +EXTRA_CONFIGURE_ARGS ?= +EXTRA_MAKE_ARGS ?= INSTALL_PATH ?= /Library/Frameworks APPLICATION_INSTALL_PATH ?= /Applications/Utilities @@ -35,7 +40,7 @@ TCL_FRAMEWORK_DIR ?= /Library/Frameworks TCLSH_DIR ?= ${PREFIX} # set to non-empty value to install manpages in addition to html help: -INSTALL_MANPAGES ?= +INSTALL_MANPAGES ?= # set to non-empty value to build TkX11 instead of TkAqua: TK_X11 ?= @@ -43,7 +48,7 @@ TK_X11 ?= #------------------------------------------------------------------------------------------------------- # meta targets -meta := all install embedded install-embedded clean distclean test +meta := all install embedded install-embedded clean distclean test styles := develop deploy @@ -84,7 +89,7 @@ deploy_make_args := BUILD_STYLE=Deployment INSTALL_TARGET=install-strip embedded_make_args := EMBEDDED_BUILD=1 install_make_args := INSTALL_BUILD=1 -${targets}: +${targets}: ${MAKE} ${action}${PROJECT} \ $(foreach s,${styles} embedded install,$(if $(findstring $s,$@),${${s}_make_args})) @@ -108,7 +113,7 @@ TCL_DIR := ${TCL_BUILD_DIR} TCL_FRAMEWORK_DIR := ${TCL_BUILD_DIR}/.. else TCL_DIR := ${TCL_FRAMEWORK_DIR}/Tcl.framework -TCL_EXE := ${TCLSH_DIR}/tclsh${TCL_VERSION} +TCL_EXE := ${TCLSH_DIR}/tclsh${TCL_VERSION} MAKE_VARS = TCL_EXE export DYLD_FRAMEWORK_PATH := ${TCL_FRAMEWORK_DIR} endif @@ -166,7 +171,7 @@ ${PROJECT}: ${MAKE} install-${PROJECT} INSTALL_ROOT=${OBJ_DIR}/ ${OBJ_DIR}/Makefile: ${UNIX_DIR}/Makefile.in ${UNIX_DIR}/configure \ - ${UNIX_DIR}/tkConfig.sh.in Tk-Info.plist.in Wish-Info.plist.in + ${UNIX_DIR}/tkConfig.sh.in Tk-Info.plist.in Wish-Info.plist.in mkdir -p ${OBJ_DIR} && cd ${OBJ_DIR} && \ if [ ${UNIX_DIR}/configure -nt config.status ]; then ${UNIX_DIR}/configure -C \ --prefix=${PREFIX} --bindir=${BINDIR} --libdir=${LIBDIR} \ @@ -291,7 +296,7 @@ clean-${PROJECT}: %-${PROJECT}: distclean-${PROJECT}: %-${PROJECT}: clean-${PROJECT} ${DO_MAKE} rm -rf ${OBJ_DIR} - + test-${PROJECT}: %-${PROJECT}: build-${PROJECT} ${DO_MAKE} diff --git a/macosx/README b/macosx/README index 4bef580..4a9c917 100644 --- a/macosx/README +++ b/macosx/README @@ -1,7 +1,7 @@ -Tcl/Tk Mac OS X README +Tcl/Tk Mac OS X README ---------------------- -RCS: @(#) $Id: README,v 1.22 2007/01/28 01:42:16 das Exp $ +RCS: @(#) $Id: README,v 1.23 2007/04/23 21:24:32 das Exp $ This is the README file for the Mac OS X/Darwin version of Tcl/Tk. @@ -98,7 +98,7 @@ inherits loginwindow's environment variables, which are essentially those set in $HOME/.MacOSX/environment.plist, and are unrelated to those set in your shell). - As of Tk 8.4.7, TkAqua has a version of the low-level drawing primitives using -the CoreGraphics routines - the code is primarily due to James Tittle. There +the CoreGraphics routines - the code is primarily due to James Tittle. There were numerous problems with the QD version, mostly due to the different drawing model of QD & Tk. CG also trivially supports dashed lines, and the various end caps & miters. The old QD code is retained for now, just in case there are any @@ -132,8 +132,8 @@ have a base name: Then to get the sequential variants, add an integer to the end of the base name. So, for instance this code will spin the spinner: proc spinCursor {widget count} { - $widget configure -cursor spinning$count - after 100 spinCursor [incr count] + $widget configure -cursor spinning$count + after 100 spinCursor [incr count] } This was added in Tk 8.4.2 @@ -238,7 +238,7 @@ Detailed Instructions for building with macosx/GNUmakefile trees in a common parent directory. [ If you don't want have the two source trees in one directory, you'll need to ] [ create the following symbolic link for the build to work as setup by default ] -[ ln -fs /path_to_tcl/build /path_to_tk/build ] +[ ln -fs /path_to_tcl/build /path_to_tk/build ] [ (where /path_to_{tcl,tk} is the directory containing the tcl resp. tk tree) ] [ or you can pass an argument of BUILD_DIR=/somewhere to the tcl and tk make. ] @@ -247,12 +247,12 @@ trees in a common parent directory. containing the Tcl and Tk version number (for example '8.4.12'). Setup the shell variable as follows: set ver="8.4.12" ;: if your shell is csh - ver="8.4.12" ;: if your shell is sh + ver="8.4.12" ;: if your shell is sh The source trees will be named this way only if you are building from a release archive, if you are building from CVS, the version numbers will be missing; so set ${ver} to the empty string instead: - set ver="" ;: if your shell is csh - ver="" ;: if your shell is sh + set ver="" ;: if your shell is csh + ver="" ;: if your shell is sh - The following steps will build Tcl and Tk from the Terminal, assuming you are located in the directory containing the tcl and tk source trees: diff --git a/macosx/Tk-Info.plist.in b/macosx/Tk-Info.plist.in index a392991..dfb0044 100644 --- a/macosx/Tk-Info.plist.in +++ b/macosx/Tk-Info.plist.in @@ -1,5 +1,13 @@ + CFBundleDevelopmentRegion @@ -7,14 +15,17 @@ CFBundleExecutable @TK_LIB_FILE@ CFBundleGetInfoString - Tk @TK_WINDOWINGSYSTEM@ Library @TK_VERSION@, Copyright © @TK_YEAR@ Tcl Core Team. -Initial MacOS X Port by Jim Ingham <jingham@apple.com> & Ian Reid, Copyright © 2001-2002, Apple Computer, Inc. + Tk @TK_WINDOWINGSYSTEM@ @TK_VERSION@@TK_PATCH_LEVEL@, +Copyright © @TK_YEAR@ Tcl Core Team, +Copyright © 2002-@TK_YEAR@ Daniel A. Steffen, +Initial MacOS X Port by Jim Ingham & Ian Reid, +Copyright © 2001-2002, Apple Computer, Inc. CFBundleIdentifier com.tcltk.tklibrary CFBundleInfoDictionaryVersion 6.0 CFBundleName - Tk @TK_WINDOWINGSYSTEM@ Library @TK_VERSION@ + Tk @TK_WINDOWINGSYSTEM@ @TK_VERSION@ CFBundlePackageType FMWK CFBundleShortVersionString diff --git a/macosx/Wish-Common.xcconfig b/macosx/Wish-Common.xcconfig index 08e041e..635fbbb 100644 --- a/macosx/Wish-Common.xcconfig +++ b/macosx/Wish-Common.xcconfig @@ -1,4 +1,4 @@ -// +// // Wish-Common.xcconfig -- // // This file contains the Xcode build settings comon to all @@ -9,12 +9,12 @@ // See the file "license.terms" for information on usage and redistribution // of this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// RCS: @(#) $Id: Wish-Common.xcconfig,v 1.2 2007/03/07 23:46:34 das Exp $ +// RCS: @(#) $Id: Wish-Common.xcconfig,v 1.3 2007/04/23 21:24:32 das Exp $ // HEADER_SEARCH_PATHS = $(TK_SRCROOT)/generic $(TK_SRCROOT)/xlib $(DERIVED_FILE_DIR)/tcl $(DERIVED_FILE_DIR)/tk $(HEADER_SEARCH_PATHS) REZ_SEARCH_PATHS = $(TK_SRCROOT)/generic $(TCL_SRCROOT)/generic $(REZ_SEARCH_PATHS) -OTHER_LDFLAGS = -headerpad_max_install_names -sectcreate __TEXT __tk_rsrc $(REZ_COLLECTOR_DIR)/$(PRODUCT_NAME).rsrc $(OTHER_LDFLAGS) +OTHER_LDFLAGS = -headerpad_max_install_names -sectcreate __TEXT __tk_rsrc $(REZ_COLLECTOR_DIR)/$(PRODUCT_NAME).rsrc -sectcreate __TEXT __info_plist $(DERIVED_FILE_DIR)/tk/Wish-Info.plist $(OTHER_LDFLAGS) INSTALL_PATH = "$(BINDIR)" GCC_PREFIX_HEADER = $(DERIVED_FILE_DIR)/tk/tkConfig.h OTHER_CFLAGS = -imacros $(DERIVED_FILE_DIR)/tcl/tclConfig.h $(OTHER_CFLAGS) @@ -25,7 +25,7 @@ GCC = /usr/bin/gcc GCC_VERSION = 4.0 CC = $(GCC)-$(GCC_VERSION) WARNING_CFLAGS_GCC3 = -Wall -Wno-implicit-int -Wno-unused-parameter -Wno-deprecated-declarations -WARNING_CFLAGS = -Wextra -Wno-missing-field-initializers $(WARNING_CFLAGS_GCC3) $(WARNING_CFLAGS) +WARNING_CFLAGS = -Wextra -Wno-missing-field-initializers -Winit-self -Wpointer-arith -Wcast-align -Wdisabled-optimization -Winline $(WARNING_CFLAGS_GCC3) $(WARNING_CFLAGS) REZ_RESOURCE_MAP_READ_ONLY = YES APPLICATION_INSTALL_PATH = /Applications/Utilities BINDIR = $(PREFIX)/bin diff --git a/macosx/Wish-Debug.xcconfig b/macosx/Wish-Debug.xcconfig index 14e80fd..19c1f71 100644 --- a/macosx/Wish-Debug.xcconfig +++ b/macosx/Wish-Debug.xcconfig @@ -1,4 +1,4 @@ -// +// // Wish-Debug.xcconfig -- // // This file contains the Xcode build settings for all Debug @@ -9,7 +9,7 @@ // See the file "license.terms" for information on usage and redistribution // of this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// RCS: @(#) $Id: Wish-Debug.xcconfig,v 1.1 2007/01/28 01:42:16 das Exp $ +// RCS: @(#) $Id: Wish-Debug.xcconfig,v 1.2 2007/04/23 21:24:32 das Exp $ // #include "Wish-Common.xcconfig" diff --git a/macosx/Wish-Info.plist.in b/macosx/Wish-Info.plist.in index 08fff5a..6cc3eef 100644 --- a/macosx/Wish-Info.plist.in +++ b/macosx/Wish-Info.plist.in @@ -1,5 +1,13 @@ + CFBundleDevelopmentRegion @@ -9,13 +17,21 @@ CFBundleTypeExtensions + tcl + TCL * + CFBundleTypeMIMETypes + + application/x-tcl + text/plain + CFBundleTypeName NSStringPboardType CFBundleTypeOSTypes TEXT + **** CFBundleTypeRole Viewer @@ -24,8 +40,11 @@ CFBundleExecutable Wish CFBundleGetInfoString - Wish Shell @TK_VERSION@, Copyright © @TK_YEAR@ Tcl Core Team. -Initial MacOS X Port by Jim Ingham <jingham@apple.com> & Ian Reid, Copyright © 2001-2002, Apple Computer, Inc. + Wish Shell @TK_VERSION@@TK_PATCH_LEVEL@, +Copyright © @TK_YEAR@ Tcl Core Team, +Copyright © 2002-@TK_YEAR@ Daniel A. Steffen, +Initial MacOS X Port by Jim Ingham & Ian Reid, +Copyright © 2001-2002, Apple Computer, Inc. CFBundleIconFile Wish.icns CFBundleIdentifier @@ -42,5 +61,11 @@ Initial MacOS X Port by Jim Ingham <jingham@apple.com> & Ian Reid, Cop WiSH CFBundleVersion @TK_VERSION@@TK_PATCH_LEVEL@ + LSMinimumSystemVersion + 10.2.0 + LSRequiresCarbon + + NSAppleScriptEnabled + diff --git a/macosx/Wish-Release.xcconfig b/macosx/Wish-Release.xcconfig index 4bcc74c..e1a8752 100644 --- a/macosx/Wish-Release.xcconfig +++ b/macosx/Wish-Release.xcconfig @@ -1,4 +1,4 @@ -// +// // Wish-Release.xcconfig -- // // This file contains the Xcode build settings for all Release @@ -9,7 +9,7 @@ // See the file "license.terms" for information on usage and redistribution // of this file, and for a DISCLAIMER OF ALL WARRANTIES. // -// RCS: @(#) $Id: Wish-Release.xcconfig,v 1.1 2007/01/28 01:42:16 das Exp $ +// RCS: @(#) $Id: Wish-Release.xcconfig,v 1.2 2007/04/23 21:24:32 das Exp $ // #include "Wish-Common.xcconfig" diff --git a/macosx/Wish.xcode/project.pbxproj b/macosx/Wish.xcode/project.pbxproj index 81abdac..6f1f009 100644 --- a/macosx/Wish.xcode/project.pbxproj +++ b/macosx/Wish.xcode/project.pbxproj @@ -75,6 +75,7 @@ F966C06F08F281DC005CB29B, 1AB674ADFE9D54B511CA2CBB, ); + comments = "Copyright (c) 2004-2007 Daniel A. Steffen \n\nSee the file \"license.terms\" for information on usage and redistribution of\nthis file, and for a DISCLAIMER OF ALL WARRANTIES.\n\nRCS: @(#) $Id: project.pbxproj,v 1.13 2007/04/23 21:24:34 das Exp $\n"; isa = PBXGroup; name = Wish; path = .; @@ -3747,7 +3748,6 @@ F966BBDB08F27A3B005CB29B, F966BBDC08F27A3B005CB29B, F966BBDD08F27A3B005CB29B, - F966BBDF08F27A3B005CB29B, F966BBE008F27A3B005CB29B, F966BBE108F27A3B005CB29B, F966BBE208F27A3B005CB29B, @@ -4021,14 +4021,6 @@ refType = 4; sourceTree = ""; }; - F966BBDF08F27A3B005CB29B = { - fileEncoding = 4; - isa = PBXFileReference; - lastKnownFileType = sourcecode.rez; - path = tkMacOSXMenu.r; - refType = 4; - sourceTree = ""; - }; F966BBE008F27A3B005CB29B = { fileEncoding = 4; isa = PBXFileReference; @@ -15036,7 +15028,6 @@ buildActionMask = 2147483647; files = ( F9EA4AF008FA3BD500B1F5F0, - F9EA4AF108FA3BD700B1F5F0, F9EA4AF208FA3BD800B1F5F0, F9EA4AF308FA3BDA00B1F5F0, F9EA4AF408FA3BDB00B1F5F0, @@ -15050,12 +15041,6 @@ settings = { }; }; - F9EA4AF108FA3BD700B1F5F0 = { - fileRef = F966BBDF08F27A3B005CB29B; - isa = PBXBuildFile; - settings = { - }; - }; F9EA4AF208FA3BD800B1F5F0 = { fileRef = F966BBCC08F27A3B005CB29B; isa = PBXBuildFile; diff --git a/macosx/Wish.xcodeproj/project.pbxproj b/macosx/Wish.xcodeproj/project.pbxproj index a0a4fbd..bcdd9f7 100644 --- a/macosx/Wish.xcodeproj/project.pbxproj +++ b/macosx/Wish.xcodeproj/project.pbxproj @@ -304,7 +304,6 @@ F9E61D31090A48F9002B3151 /* bn_mp_to_unsigned_bin.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42C608F272B3004A47F5 /* bn_mp_to_unsigned_bin.c */; }; F9E61D32090A48FA002B3151 /* bn_mp_unsigned_bin_size.c in Sources */ = {isa = PBXBuildFile; fileRef = F96D42CC08F272B3004A47F5 /* bn_mp_unsigned_bin_size.c */; }; F9EA4AF008FA3BD500B1F5F0 /* tkMacOSXXCursors.r in Rez */ = {isa = PBXBuildFile; fileRef = F966BBF408F27A3C005CB29B /* tkMacOSXXCursors.r */; }; - F9EA4AF108FA3BD700B1F5F0 /* tkMacOSXMenu.r in Rez */ = {isa = PBXBuildFile; fileRef = F966BBDF08F27A3B005CB29B /* tkMacOSXMenu.r */; }; F9EA4AF208FA3BD800B1F5F0 /* tkMacOSXCursors.r in Rez */ = {isa = PBXBuildFile; fileRef = F966BBCC08F27A3B005CB29B /* tkMacOSXCursors.r */; }; F9EA4AF308FA3BDA00B1F5F0 /* tkMacOSXAETE.r in Rez */ = {isa = PBXBuildFile; fileRef = F966BBC408F27A3B005CB29B /* tkMacOSXAETE.r */; }; F9EA4AF408FA3BDB00B1F5F0 /* tkAboutDlg.r in Rez */ = {isa = PBXBuildFile; fileRef = F966BBC108F27A3B005CB29B /* tkAboutDlg.r */; }; @@ -698,7 +697,6 @@ F966BBDB08F27A3B005CB29B /* tkMacOSXKeyboard.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkMacOSXKeyboard.c; sourceTree = ""; }; F966BBDC08F27A3B005CB29B /* tkMacOSXKeyEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkMacOSXKeyEvent.c; sourceTree = ""; }; F966BBDD08F27A3B005CB29B /* tkMacOSXMenu.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkMacOSXMenu.c; sourceTree = ""; }; - F966BBDF08F27A3B005CB29B /* tkMacOSXMenu.r */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.rez; path = tkMacOSXMenu.r; sourceTree = ""; }; F966BBE008F27A3B005CB29B /* tkMacOSXMenubutton.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkMacOSXMenubutton.c; sourceTree = ""; }; F966BBE108F27A3B005CB29B /* tkMacOSXMenus.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkMacOSXMenus.c; sourceTree = ""; }; F966BBE208F27A3B005CB29B /* tkMacOSXMouseEvent.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = tkMacOSXMouseEvent.c; sourceTree = ""; }; @@ -1788,6 +1786,7 @@ F966C06F08F281DC005CB29B /* Frameworks */, 1AB674ADFE9D54B511CA2CBB /* Products */, ); + comments = "Copyright (c) 2004-2007 Daniel A. Steffen \n\nSee the file \"license.terms\" for information on usage and redistribution of\nthis file, and for a DISCLAIMER OF ALL WARRANTIES.\n\nRCS: @(#) $Id: project.pbxproj,v 1.19 2007/04/23 21:24:35 das Exp $\n"; name = Wish; path = .; sourceTree = SOURCE_ROOT; @@ -2252,7 +2251,6 @@ F966BBDB08F27A3B005CB29B /* tkMacOSXKeyboard.c */, F966BBDC08F27A3B005CB29B /* tkMacOSXKeyEvent.c */, F966BBDD08F27A3B005CB29B /* tkMacOSXMenu.c */, - F966BBDF08F27A3B005CB29B /* tkMacOSXMenu.r */, F966BBE008F27A3B005CB29B /* tkMacOSXMenubutton.c */, F966BBE108F27A3B005CB29B /* tkMacOSXMenus.c */, F966BBE208F27A3B005CB29B /* tkMacOSXMouseEvent.c */, @@ -3601,7 +3599,6 @@ buildActionMask = 2147483647; files = ( F9EA4AF008FA3BD500B1F5F0 /* tkMacOSXXCursors.r in Rez */, - F9EA4AF108FA3BD700B1F5F0 /* tkMacOSXMenu.r in Rez */, F9EA4AF208FA3BD800B1F5F0 /* tkMacOSXCursors.r in Rez */, F9EA4AF308FA3BDA00B1F5F0 /* tkMacOSXAETE.r in Rez */, F9EA4AF408FA3BDB00B1F5F0 /* tkAboutDlg.r in Rez */, @@ -4013,6 +4010,30 @@ }; name = ReleaseUniversal; }; + F94173790BC145DD00C54E27 /* DebugMemCompile */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = Wish; + }; + name = DebugMemCompile; + }; + F941737A0BC145DD00C54E27 /* DebugMemCompile */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = tktest; + }; + name = DebugMemCompile; + }; + F941737B0BC145DD00C54E27 /* DebugMemCompile */ = { + isa = XCBuildConfiguration; + baseConfigurationReference = F97AE8330B65C87F00310EA2 /* Wish-Debug.xcconfig */; + buildSettings = { + CONFIGURE_ARGS = "$(CONFIGURE_ARGS) --enable-symbols=all"; + MACOSX_DEPLOYMENT_TARGET = 10.2; + PREBINDING = NO; + }; + name = DebugMemCompile; + }; F95CC8AC09158F3100EA5ACE /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -4037,6 +4058,7 @@ F95CC8B109158F3100EA5ACE /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + CONFIGURE_ARGS = "tcl_cv_cc_visibility_hidden=no $(CONFIGURE_ARGS)"; GCC_ENABLE_FIX_AND_CONTINUE = YES; GCC_PREPROCESSOR_DEFINITIONS = ( "__private_extern__=extern", @@ -4188,6 +4210,7 @@ buildConfigurations = ( F95CC8AC09158F3100EA5ACE /* Debug */, F95CC8AE09158F3100EA5ACE /* DebugNoFixZL */, + F94173790BC145DD00C54E27 /* DebugMemCompile */, F95CC8AD09158F3100EA5ACE /* Release */, F91BCC4F093152310042A6BF /* ReleaseUniversal */, F9DB62080B65ADA800A370FB /* ReleaseUniversal10.4uSDK */, @@ -4202,6 +4225,7 @@ buildConfigurations = ( F95CC8B109158F3100EA5ACE /* Debug */, F95CC8B309158F3100EA5ACE /* DebugNoFixZL */, + F941737A0BC145DD00C54E27 /* DebugMemCompile */, F95CC8B209158F3100EA5ACE /* Release */, F91BCC50093152310042A6BF /* ReleaseUniversal */, F9DB62090B65ADA800A370FB /* ReleaseUniversal10.4uSDK */, @@ -4216,6 +4240,7 @@ buildConfigurations = ( F95CC8B609158F3100EA5ACE /* Debug */, F95CC8B809158F3100EA5ACE /* DebugNoFixZL */, + F941737B0BC145DD00C54E27 /* DebugMemCompile */, F95CC8B709158F3100EA5ACE /* Release */, F91BCC51093152310042A6BF /* ReleaseUniversal */, F9DB620A0B65ADA800A370FB /* ReleaseUniversal10.4uSDK */, diff --git a/macosx/tkAboutDlg.r b/macosx/tkAboutDlg.r index 3bbdc28..9f42997 100644 --- a/macosx/tkAboutDlg.r +++ b/macosx/tkAboutDlg.r @@ -1,16 +1,15 @@ /* * tkAboutDlg.r -- * - * This file creates resources for use in most Tk applications. - * This is designed to be an example of using the Tcl/Tk - * libraries in a Macintosh Application. + * This file creates resources for the Tk "About Box" dialog. * * Copyright (c) 1996 Sun Microsystems, Inc. + * Copyright (c) 2006-2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkAboutDlg.r,v 1.7 2006/04/28 06:02:48 das Exp $ + * RCS: @(#) $Id: tkAboutDlg.r,v 1.8 2007/04/23 21:24:32 das Exp $ */ /* @@ -26,15 +25,15 @@ /* * The following two resources define the default "About Box" for Mac Tk. * This dialog appears if the "About Tk..." menu item is selected from - * the Apple menu. This dialog may be overridden by defining a Tcl procedure - * with the name of "tkAboutDialog". If this procedure is defined the + * the Apple menu. This dialog may be overridden by defining a Tcl procedure + * with the name of "tkAboutDialog". If this procedure is defined the * default dialog will not be shown and the Tcl procedure is expected to * create and manage an About Dialog box. */ - + resource 'DLOG' (128, "About Box", purgeable) { {60, 40, 332, 404}, - movableDBoxProc, + kWindowMovableModalDialogProc, visible, noGoAway, 0x0, @@ -46,19 +45,26 @@ resource 'DLOG' (128, "About Box", purgeable) { resource 'DITL' (128, "About Box", purgeable) { { {232, 147, 252, 217}, Button {enabled, "Ok"}, - { 20, 108, 212, 344}, StaticText {disabled, - "Tcl " TCL_PATCH_LEVEL " & Tk " TK_PATCH_LEVEL "\n\n" - "© 2002-2006 Tcl Core Team." "\n\n" - "© 2002-2006 Daniel A. Steffen." "\n\n" + { 20, 108, 212, 344}, StaticText {disabled, + "Tcl " TCL_PATCH_LEVEL " & Tk " TK_PATCH_LEVEL "\n\n" + "© 2002-2007 Tcl Core Team." "\n\n" + "© 2002-2007 Daniel A. Steffen." "\n\n" "Jim Ingham & Ian Reid" "\n" - "© 2001-2002 Apple Computer, Inc." "\n\n" + "© 2001-2002 Apple Computer, Inc." "\n\n" "Jim Ingham & Ray Johnson" "\n" "© 1998-2000 Scriptics Inc." "\n" - "© 1996-1997 Sun Microsystems Inc."}, + "© 1996-1997 Sun Microsystems Inc."}, { 20, 24, 120, 92}, Picture {enabled, 128} } }; +resource 'dlgx' (128, "About Box", purgeable) { + versionZero { + kDialogFlagsUseThemeBackground | kDialogFlagsUseControlHierarchy + | kDialogFlagsHandleMovableModal | kDialogFlagsUseThemeControls + } +}; + data 'PICT' (128, purgeable) { $"13A4 0000 0000 0064 0044 0011 02FF 0C00" $"FFFE 0000 0048 0000 0048 0000 0000 0000" diff --git a/macosx/tkMacOSX.h b/macosx/tkMacOSX.h index 1fb92f4..4b92458 100644 --- a/macosx/tkMacOSX.h +++ b/macosx/tkMacOSX.h @@ -5,11 +5,12 @@ * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2005-2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSX.h,v 1.4 2006/03/24 14:58:00 das Exp $ + * RCS: @(#) $Id: tkMacOSX.h,v 1.5 2007/04/23 21:24:32 das Exp $ */ #ifndef _TKMAC @@ -25,11 +26,11 @@ * Structures and function types for handling Netscape-type in process * embedding where Tk does not control the top-level */ - -typedef int (Tk_MacOSXEmbedRegisterWinProc) (int winID, Tk_Window window); -typedef GWorldPtr (Tk_MacOSXEmbedGetGrafPortProc) (Tk_Window window); -typedef int (Tk_MacOSXEmbedMakeContainerExistProc) (Tk_Window window); -typedef void (Tk_MacOSXEmbedGetClipProc) (Tk_Window window, RgnHandle rgn); + +typedef int (Tk_MacOSXEmbedRegisterWinProc) (int winID, Tk_Window window); +typedef GWorldPtr (Tk_MacOSXEmbedGetGrafPortProc) (Tk_Window window); +typedef int (Tk_MacOSXEmbedMakeContainerExistProc) (Tk_Window window); +typedef void (Tk_MacOSXEmbedGetClipProc) (Tk_Window window, RgnHandle rgn); typedef void (Tk_MacOSXEmbedGetOffsetInParentProc) (Tk_Window window, Point *ulCorner); #include "tkPlatDecls.h" diff --git a/macosx/tkMacOSXAETE.r b/macosx/tkMacOSXAETE.r index 86b860d..87f2a73 100644 --- a/macosx/tkMacOSXAETE.r +++ b/macosx/tkMacOSXAETE.r @@ -1,18 +1,15 @@ /* * tclMacAETE.r -- * - * This file creates the Apple Event Terminology resources - * for use Tcl and Tk. It is not used in the Simple Tcl shell - * since SIOUX does not support AppleEvents. An example of its - * use in Tcl is the TclBGOnly project. And it is used in all the - * Tk Shells. + * This file creates the Apple Event Terminology resources + * for use by Wish.app. * * Copyright (c) 1997 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXAETE.r,v 1.1 2003/02/25 18:24:31 wolfsuit Exp $ + * RCS: @(#) $Id: tkMacOSXAETE.r,v 1.2 2007/04/23 21:24:32 das Exp $ */ #define SystemSevenOrLater 1 @@ -27,8 +24,8 @@ resource 'aete' (0, "Wish Suite") { 0x01, 0x00, english, roman, { - "Required Suite", - "Events that every application should support", + "Required Suite", + "Events that every application should support", 'reqd', 1, 1, {}, {}, @@ -41,12 +38,12 @@ resource 'aete' (0, "Wish Suite") { 'TEXT', "Result", replyOptional, singleItem, notEnumerated, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, - reserved, reserved, reserved, reserved, + reserved, reserved, reserved, reserved, 'TEXT', "Script to execute", directParamRequired, singleItem, notEnumerated, changesState, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, reserved, - reserved, + reserved, {}, }, {}, diff --git a/macosx/tkMacOSXBitmap.c b/macosx/tkMacOSXBitmap.c index dc05bc8..7b66a38 100644 --- a/macosx/tkMacOSXBitmap.c +++ b/macosx/tkMacOSXBitmap.c @@ -1,15 +1,16 @@ -/* +/* * tkMacOSXBitmap.c -- * - * This file handles the implementation of native bitmaps. + * This file handles the implementation of native bitmaps. * * Copyright (c) 1996-1997 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2006-2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXBitmap.c,v 1.6 2007/04/21 19:06:37 hobbs Exp $ + * RCS: @(#) $Id: tkMacOSXBitmap.c,v 1.7 2007/04/23 21:24:32 das Exp $ */ #include "tkMacOSXInt.h" @@ -18,17 +19,17 @@ * Depending on the resource type there are different ways to * draw native icons. */ -#define TYPE1 0 /* Family icon suite. */ -#define TYPE2 1 /* ICON resource. */ -#define TYPE3 2 /* cicn resource. */ +#define TYPE1 0 /* Family icon suite. */ +#define TYPE2 1 /* ICON resource. */ +#define TYPE3 2 /* cicn resource. */ /* * This data structure describes the id and type of a given icon. * It is used as the source for native icons. */ typedef struct { - int id; /* Resource Id for Icon. */ - long int type; /* Type of icon. */ + int id; /* Resource Id for Icon. */ + long int type; /* Type of icon. */ } NativeIcon; /* @@ -36,10 +37,10 @@ typedef struct { */ typedef struct { - char *name; /* Name of icon. */ - long int type; /* Type of icon. */ - int id; /* Id of icon. */ - int size; /* Size of icon. */ + const char *name; /* Name of icon. */ + long int type; /* Type of icon. */ + int id; /* Id of icon. */ + int size; /* Size of icon. */ } BuiltInIcon; /* @@ -48,23 +49,23 @@ typedef struct { */ static BuiltInIcon builtInIcons[] = { - {"document", TYPE1, kGenericDocumentIconResource, 32}, - {"stationery", TYPE1, kGenericStationeryIconResource, 32}, - {"edition", TYPE1, kGenericEditionFileIconResource, 32}, - {"application", TYPE1, kGenericApplicationIconResource, 32}, - {"accessory", TYPE1, kGenericDeskAccessoryIconResource, 32}, - {"folder", TYPE1, kGenericFolderIconResource, 32}, - {"pfolder", TYPE1, kPrivateFolderIconResource, 32}, - {"trash", TYPE1, kTrashIconResource, 32}, - {"floppy", TYPE1, kFloppyIconResource, 32}, - {"ramdisk", TYPE1, kGenericRAMDiskIconResource, 32}, - {"cdrom", TYPE1, kGenericCDROMIconResource, 32}, - {"preferences", TYPE1, kGenericPreferencesIconResource, 32}, - {"querydoc", TYPE1, kGenericQueryDocumentIconResource, 32}, - {"stop", TYPE2, kStopIcon, 32}, - {"note", TYPE2, kNoteIcon, 32}, - {"caution", TYPE2, kCautionIcon, 32}, - {(char *) NULL, 0, 0, 0} + {"document", TYPE1, kGenericDocumentIconResource, 32}, + {"stationery", TYPE1, kGenericStationeryIconResource, 32}, + {"edition", TYPE1, kGenericEditionFileIconResource, 32}, + {"application", TYPE1, kGenericApplicationIconResource, 32}, + {"accessory", TYPE1, kGenericDeskAccessoryIconResource, 32}, + {"folder", TYPE1, kGenericFolderIconResource, 32}, + {"pfolder", TYPE1, kPrivateFolderIconResource, 32}, + {"trash", TYPE1, kTrashIconResource, 32}, + {"floppy", TYPE1, kFloppyIconResource, 32}, + {"ramdisk", TYPE1, kGenericRAMDiskIconResource, 32}, + {"cdrom", TYPE1, kGenericCDROMIconResource, 32}, + {"preferences", TYPE1, kGenericPreferencesIconResource, 32}, + {"querydoc", TYPE1, kGenericQueryDocumentIconResource, 32}, + {"stop", TYPE2, kStopIcon, 32}, + {"note", TYPE2, kNoteIcon, 32}, + {"caution", TYPE2, kCautionIcon, 32}, + {NULL, 0, 0, 0} }; /* @@ -72,46 +73,46 @@ static BuiltInIcon builtInIcons[] = { * * TkpDefineNativeBitmaps -- * - * Add native bitmaps. + * Add native bitmaps. * * Results: - * A standard Tcl result. If an error occurs then TCL_ERROR is - * returned and a message is left in the interp's result. + * A standard Tcl result. If an error occurs then TCL_ERROR is + * returned and a message is left in the interp's result. * * Side effects: - * "Name" is entered into the bitmap table and may be used from - * here on to refer to the given bitmap. + * "Name" is entered into the bitmap table and may be used from + * here on to refer to the given bitmap. * *---------------------------------------------------------------------- */ void -TkpDefineNativeBitmaps() +TkpDefineNativeBitmaps(void) { - int new; - Tcl_HashEntry *predefHashPtr; - TkPredefBitmap *predefPtr; - CONST char * name; + Tcl_HashTable *tablePtr = TkGetBitmapPredefTable(); BuiltInIcon *builtInPtr; - NativeIcon *nativeIconPtr; - Tcl_HashTable *tablePtr; - + for (builtInPtr = builtInIcons; builtInPtr->name != NULL; builtInPtr++) { - name = Tk_GetUid(builtInPtr->name); - tablePtr = TkGetBitmapPredefTable(); - predefHashPtr = Tcl_CreateHashEntry(tablePtr, name, &new); - if (!new) { - continue; - } - predefPtr = (TkPredefBitmap *) ckalloc(sizeof(TkPredefBitmap)); - nativeIconPtr = (NativeIcon *) ckalloc(sizeof(NativeIcon)); - nativeIconPtr->id = builtInPtr->id; - nativeIconPtr->type = builtInPtr->type; - predefPtr->source = (char *) nativeIconPtr; - predefPtr->width = builtInPtr->size; - predefPtr->height = builtInPtr->size; - predefPtr->native = 1; - Tcl_SetHashValue(predefHashPtr, predefPtr); + Tcl_HashEntry *predefHashPtr; + const char * name; + int isNew; + + name = Tk_GetUid(builtInPtr->name); + predefHashPtr = Tcl_CreateHashEntry(tablePtr, name, &isNew); + if (isNew) { + TkPredefBitmap *predefPtr = (TkPredefBitmap *) + ckalloc(sizeof(TkPredefBitmap)); + NativeIcon *nativeIconPtr = (NativeIcon *) + ckalloc(sizeof(NativeIcon)); + + nativeIconPtr->id = builtInPtr->id; + nativeIconPtr->type = builtInPtr->type; + predefPtr->source = (char *) nativeIconPtr; + predefPtr->width = builtInPtr->size; + predefPtr->height = builtInPtr->size; + predefPtr->native = 1; + Tcl_SetHashValue(predefHashPtr, predefPtr); + } } } @@ -120,15 +121,15 @@ TkpDefineNativeBitmaps() * * TkpCreateNativeBitmap -- * - * Add native bitmaps. + * Add native bitmaps. * * Results: - * A standard Tcl result. If an error occurs then TCL_ERROR is - * returned and a message is left in the interp's result. + * A standard Tcl result. If an error occurs then TCL_ERROR is + * returned and a message is left in the interp's result. * * Side effects: - * "Name" is entered into the bitmap table and may be used from - * here on to refer to the given bitmap. + * "Name" is entered into the bitmap table and may be used from + * here on to refer to the given bitmap. * *---------------------------------------------------------------------- */ @@ -136,42 +137,40 @@ TkpDefineNativeBitmaps() Pixmap TkpCreateNativeBitmap( Display *display, - CONST char * source) /* Info about the icon to build. */ + CONST char *source) /* Info about the icon to build. */ { Pixmap pix; - GWorldPtr destPort; Rect destRect; - Handle icon; - CGrafPtr saveWorld; - GDHandle saveDevice; - NativeIcon *nativeIconPtr; - - pix = Tk_GetPixmap(display, None, 32, 32, 0); - destPort = TkMacOSXGetDrawablePort(pix); + CGrafPtr savePort; + Boolean portChanged; + const NativeIcon *nativeIconPtr; - GetGWorld(&saveWorld, &saveDevice); - SetGWorld(destPort, NULL); + pix = Tk_GetPixmap(display, None, 32, 32, 0); + portChanged = QDSwapPort(TkMacOSXGetDrawablePort(pix), &savePort); - nativeIconPtr = (NativeIcon *) source; + nativeIconPtr = (const NativeIcon *) source; SetRect(&destRect, 0, 0, 32, 32); if (nativeIconPtr->type == TYPE1) { - RGBColor white = {0xFFFF, 0xFFFF, 0xFFFF}; + RGBColor white = {0xFFFF, 0xFFFF, 0xFFFF}; - RGBForeColor(&white); - PaintRect(&destRect); - PlotIconID(&destRect, atAbsoluteCenter, ttNone, nativeIconPtr->id); + RGBForeColor(&white); + PaintRect(&destRect); + PlotIconID(&destRect, atAbsoluteCenter, ttNone, nativeIconPtr->id); } else if (nativeIconPtr->type == TYPE2) { - icon = GetIcon(nativeIconPtr->id); - if (icon != NULL) { - RGBColor black = {0, 0, 0}; - - RGBForeColor(&black); - PlotIcon(&destRect, icon); - ReleaseResource(icon); - } + Handle icon = GetIcon(nativeIconPtr->id); + + if (icon != NULL) { + RGBColor black = {0, 0, 0}; + + RGBForeColor(&black); + PlotIcon(&destRect, icon); + ReleaseResource(icon); + } } - SetGWorld(saveWorld, saveDevice); + if (portChanged) { + QDSwapPort(savePort, NULL); + } return pix; } @@ -180,94 +179,94 @@ TkpCreateNativeBitmap( * * TkpGetNativeAppBitmap -- * - * Add native bitmaps. + * Add native bitmaps. * * Results: - * A standard Tcl result. If an error occurs then TCL_ERROR is - * returned and a message is left in the interp's result. + * A standard Tcl result. If an error occurs then TCL_ERROR is + * returned and a message is left in the interp's result. * * Side effects: - * "Name" is entered into the bitmap table and may be used from - * here on to refer to the given bitmap. + * "Name" is entered into the bitmap table and may be used from + * here on to refer to the given bitmap. * *---------------------------------------------------------------------- */ Pixmap TkpGetNativeAppBitmap( - Display *display, /* The display. */ - CONST char *name, /* The name of the bitmap. */ - int *width, /* The width & height of the bitmap. */ + Display *display, /* The display. */ + CONST char *name, /* The name of the bitmap. */ + int *width, /* The width & height of the bitmap. */ int *height) { Pixmap pix; - CGrafPtr saveWorld; - GDHandle saveDevice; - GWorldPtr destPort; + CGrafPtr savePort; + Boolean portChanged; Rect destRect; Handle resource; int type = -1, destWrote; Str255 nativeName; - + Tcl_Encoding encoding; + /* * macRoman is the encoding that the resource fork uses. */ - Tcl_UtfToExternal(NULL, Tcl_GetEncoding(NULL, "macRoman"), name, - strlen(name), 0, NULL, - (char *) &nativeName[1], - 255, NULL, &destWrote, NULL); /* Internalize native */ + encoding = Tcl_GetEncoding(NULL, "macRoman"); + Tcl_UtfToExternal(NULL, encoding, name, strlen(name), 0, NULL, + (char *) &nativeName[1], 255, NULL, &destWrote, NULL); nativeName[0] = destWrote; + Tcl_FreeEncoding(encoding); resource = GetNamedResource('cicn', nativeName); if (resource != NULL) { - type = TYPE3; + type = TYPE3; } else { - resource = GetNamedResource('ICON', nativeName); - if (resource != NULL) { - type = TYPE2; - } + resource = GetNamedResource('ICON', nativeName); + if (resource != NULL) { + type = TYPE2; + } } - + if (resource == NULL) { - return (Pixmap) NULL; + return (Pixmap) NULL; } - + pix = Tk_GetPixmap(display, None, 32, 32, 0); - destPort = TkMacOSXGetDrawablePort(pix); + portChanged = QDSwapPort(TkMacOSXGetDrawablePort(pix), &savePort); - GetGWorld(&saveWorld, &saveDevice); - SetGWorld(destPort, NULL); - SetRect(&destRect, 0, 0, 32, 32); if (type == TYPE2) { - RGBColor black = {0, 0, 0}; - - RGBForeColor(&black); - PlotIcon(&destRect, resource); - ReleaseResource(resource); + RGBColor black = {0, 0, 0}; + + RGBForeColor(&black); + PlotIcon(&destRect, resource); + ReleaseResource(resource); } else if (type == TYPE3) { - RGBColor white = {0xFFFF, 0xFFFF, 0xFFFF}; - short id; - ResType theType; - Str255 dummy; - - /* - * We need to first paint the background white. Also, for - * some reason we *must* use GetCIcon instead of GetNamedResource - * for PlotCIcon to work - so we use GetResInfo to get the id. - */ - RGBForeColor(&white); - PaintRect(&destRect); - GetResInfo(resource, &id, &theType, dummy); - ReleaseResource(resource); - resource = (Handle) GetCIcon(id); - PlotCIcon(&destRect, (CIconHandle) resource); - DisposeCIcon((CIconHandle) resource); + RGBColor white = {0xFFFF, 0xFFFF, 0xFFFF}; + short id; + ResType theType; + Str255 dummy; + + /* + * We need to first paint the background white. Also, for + * some reason we *must* use GetCIcon instead of GetNamedResource + * for PlotCIcon to work - so we use GetResInfo to get the id. + */ + + RGBForeColor(&white); + PaintRect(&destRect); + GetResInfo(resource, &id, &theType, dummy); + ReleaseResource(resource); + resource = (Handle) GetCIcon(id); + PlotCIcon(&destRect, (CIconHandle) resource); + DisposeCIcon((CIconHandle) resource); } - + *width = 32; *height = 32; - SetGWorld(saveWorld, saveDevice); + if (portChanged) { + QDSwapPort(savePort, NULL); + } return pix; } diff --git a/macosx/tkMacOSXButton.c b/macosx/tkMacOSXButton.c index 84addc5..dadf6cb 100644 --- a/macosx/tkMacOSXButton.c +++ b/macosx/tkMacOSXButton.c @@ -1,16 +1,17 @@ -/* +/* * tkMacOSXButton.c -- * - * This file implements the Macintosh specific portion of the - * button widgets. + * This file implements the Macintosh specific portion of the + * button widgets. * * Copyright (c) 1996-1997 by Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2006-2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXButton.c,v 1.22 2007/04/21 19:06:37 hobbs Exp $ + * RCS: @(#) $Id: tkMacOSXButton.c,v 1.23 2007/04/23 21:24:33 das Exp $ */ #include "tkMacOSXInt.h" @@ -23,6 +24,7 @@ /* * Default insets for controls */ + #define DEF_INSET_LEFT 2 #define DEF_INSET_RIGHT 2 #define DEF_INSET_TOP 2 @@ -37,7 +39,7 @@ #define DRAW_CUSTOM 2 /* Make our own button drawing. */ #define DRAW_BEVEL 3 -/* +/* * Declaration of Mac specific button structure. */ @@ -46,43 +48,42 @@ typedef struct { SInt16 minValue; SInt16 maxValue; SInt16 procID; - int isBevel; + int isBevel; } MacControlParams; typedef struct { int drawType; Tk_3DBorder border; int relief; - int offset; /* 0 means this is a normal widget. 1 means + int offset; /* 0 means this is a normal widget. 1 means * it is an image button, so we offset the * image to make the button appear to move * up and down as the relief changes. */ - GC gc; + GC gc; int hasImageOrBitmap; } DrawParams; - typedef struct { - TkButton info; /* generic button info */ - int id; - int usingControl; - int useTkText; - int flags; /* initialisation status */ - MacControlParams params; - WindowRef windowRef; - RGBColor userPaneBackground; - ControlRef userPane; /* Carbon control */ - ControlRef control; /* Carbon control */ - Str255 controlTitle; - ControlFontStyleRec fontStyle; - /* - * the following are used to store the image content for - * beveled buttons - i.e. buttons with images. + TkButton info; /* Generic button info */ + int id; + int usingControl; + int useTkText; + int flags; /* Initialisation status */ + MacControlParams params; + WindowRef windowRef; + unsigned long userPaneBackground; + ControlRef userPane; /* Carbon control */ + ControlRef control; /* Carbon control */ + Str255 controlTitle; + ControlFontStyleRec fontStyle; + /* + * The following are used to store the image content for + * beveled buttons, i.e. buttons with images. */ - CCTabHandle tabHandle; + CCTabHandle tabHandle; + Pixmap picPixmap; ControlButtonContentInfo bevelButtonContent; - OpenCPicParams picParams; - Pixmap picPixmap; + OpenCPicParams picParams; } MacButton; /* @@ -90,31 +91,31 @@ typedef struct { */ -static OSErr SetUserPaneDrawProc(ControlRef control, - ControlUserPaneDrawProcPtr upp); -static OSErr SetUserPaneSetUpSpecialBackgroundProc(ControlRef control, - ControlUserPaneBackgroundProcPtr upp); +static OSStatus SetUserPaneDrawProc(ControlRef control, + ControlUserPaneDrawProcPtr upp); +static OSStatus SetUserPaneSetUpSpecialBackgroundProc(ControlRef control, + ControlUserPaneBackgroundProcPtr upp); static void UserPaneDraw(ControlRef control, ControlPartCode cpc); static void UserPaneBackgroundProc(ControlHandle, - ControlBackgroundPtr info); - -static void ButtonEventProc _ANSI_ARGS_(( ClientData clientData, XEvent *eventPtr)); -static int UpdateControlColors _ANSI_ARGS_((MacButton *mbPtr )); -static void TkMacOSXComputeControlParams _ANSI_ARGS_((TkButton * butPtr, MacControlParams * paramsPtr)); -static int TkMacOSXComputeDrawParams _ANSI_ARGS_((TkButton * butPtr, DrawParams * dpPtr)); -static void TkMacOSXDrawControl _ANSI_ARGS_((MacButton *butPtr, - GWorldPtr destPort, GC gc, Pixmap pixmap)); -static void SetupBevelButton _ANSI_ARGS_((MacButton *butPtr, - ControlRef controlHandle, - GWorldPtr destPort, GC gc, Pixmap pixmap)); + ControlBackgroundPtr info); + +static void ButtonEventProc(ClientData clientData, XEvent *eventPtr); +static int UpdateControlColors(MacButton *mbPtr); +static void TkMacOSXComputeControlParams(TkButton *butPtr, + MacControlParams *paramsPtr); +static int TkMacOSXComputeDrawParams(TkButton *butPtr, DrawParams *dpPtr); +static void TkMacOSXDrawControl(MacButton *butPtr, GWorldPtr destPort, GC gc, + Pixmap pixmap); +static void SetupBevelButton(MacButton *butPtr, ControlRef controlHandle, + GWorldPtr destPort, GC gc, Pixmap pixmap); /* * The class procedure table for the button widgets. */ -Tk_ClassProcs tkpButtonProcs = { - sizeof(Tk_ClassProcs), /* size */ - TkButtonWorldChanged, /* worldChangedProc */ +Tk_ClassProcs tkpButtonProcs = { + sizeof(Tk_ClassProcs), /* size */ + TkButtonWorldChanged, /* worldChangedProc */ }; static int bCount; @@ -126,13 +127,13 @@ int tkPictureIsOpen; * * TkpCreateButton -- * - * Allocate a new TkButton structure. + * Allocate a new TkButton structure. * * Results: - * Returns a newly allocated TkButton structure. + * Returns a newly allocated TkButton structure. * * Side effects: - * Registers an event handler for the widget. + * Registers an event handler for the widget. * *---------------------------------------------------------------------- */ @@ -141,16 +142,14 @@ TkButton * TkpCreateButton( Tk_Window tkwin) { - MacButton *macButtonPtr; - macButtonPtr = (MacButton *) ckalloc(sizeof(MacButton)); + MacButton *macButtonPtr = (MacButton *) ckalloc(sizeof(MacButton)); + Tk_CreateEventHandler(tkwin, ActivateMask, - ButtonEventProc, (ClientData) macButtonPtr); + ButtonEventProc, (ClientData) macButtonPtr); macButtonPtr->id = bCount++; macButtonPtr->usingControl = 0; macButtonPtr->flags = 0; - macButtonPtr->userPaneBackground.red = 0; - macButtonPtr->userPaneBackground.green = 0; - macButtonPtr->userPaneBackground.blue = ~0; + macButtonPtr->userPaneBackground = PIXEL_MAGIC << 24; macButtonPtr->userPane = NULL; macButtonPtr->control = NULL; macButtonPtr->controlTitle[0] = 0; @@ -165,6 +164,7 @@ TkpCreateButton( macButtonPtr->bevelButtonContent.contentType = kControlContentPictHandle; bzero(&macButtonPtr->params, sizeof(macButtonPtr->params)); bzero(&macButtonPtr->fontStyle,sizeof(macButtonPtr->fontStyle)); + return (TkButton *)macButtonPtr; } @@ -173,309 +173,300 @@ TkpCreateButton( * * TkpDisplayButton -- * - * This procedure is invoked to display a button widget. It is - * normally invoked as an idle handler. + * This procedure is invoked to display a button widget. It is + * normally invoked as an idle handler. * * Results: - * None. + * None. * * Side effects: - * Commands are output to X to display the button in its - * current mode. The REDRAW_PENDING flag is cleared. + * Commands are output to X to display the button in its + * current mode. The REDRAW_PENDING flag is cleared. * *---------------------------------------------------------------------- */ void TkpDisplayButton( - ClientData clientData) /* Information about widget. */ + ClientData clientData) /* Information about widget. */ { MacButton *macButtonPtr = (MacButton *)clientData; - TkButton *butPtr = (TkButton *) clientData; - Tk_Window tkwin = butPtr->tkwin; - int width, height, fullWidth, fullHeight; - int textXOffset, textYOffset; - int haveImage = 0, haveText = 0; - GWorldPtr destPort; - int borderWidth; + TkButton *butPtr = (TkButton *) clientData; + Tk_Window tkwin = butPtr->tkwin; + CGrafPtr destPort, savePort; + Boolean portChanged; Pixmap pixmap; - int wasUsingControl; - int imageWidth = 0, imageHeight = 0; + int width, height, fullWidth, fullHeight, textXOffset, textYOffset; + int borderWidth, wasUsingControl; + int haveImage = 0, haveText = 0, imageWidth = 0, imageHeight = 0; int imageXOffset = 0, imageYOffset = 0; /* image information that will * be used to restrict disabled * pixmap as well */ - DrawParams drawParams, * dpPtr = &drawParams; + DrawParams drawParams, *dpPtr = &drawParams; butPtr->flags &= ~REDRAW_PENDING; if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { - return; + return; } pixmap = (Pixmap) Tk_WindowId(tkwin); wasUsingControl = macButtonPtr->usingControl; if (TkMacOSXComputeDrawParams(butPtr, &drawParams) ) { - macButtonPtr->usingControl = 1; - if (butPtr->type == TYPE_BUTTON) { - macButtonPtr->useTkText = 0; - } else { - macButtonPtr->useTkText = 1; - } + macButtonPtr->usingControl = 1; + if (butPtr->type == TYPE_BUTTON) { + macButtonPtr->useTkText = 0; + } else { + macButtonPtr->useTkText = 1; + } } else { - macButtonPtr->usingControl = 0; - macButtonPtr->useTkText = 1; + macButtonPtr->usingControl = 0; + macButtonPtr->useTkText = 1; } - - /* - * set up clipping region. Make sure the we are using the port - * for this button, or we will set the wrong window's clip. + + /* + * Set up clipping region. Make sure the we are using the port + * for this button, or we will set the wrong window's clip. */ - + destPort = TkMacOSXGetDrawablePort(pixmap); - SetGWorld(destPort, NULL); + portChanged = QDSwapPort(destPort, &savePort); TkMacOSXSetUpClippingRgn(pixmap); - /* - * See the comment in UpdateControlColors as to why we use the + * See the comment in UpdateControlColors as to why we use the * highlightbackground for the border of Macintosh buttons. */ if (macButtonPtr->useTkText) { - if (butPtr->type == TYPE_BUTTON) { - Tk_Fill3DRectangle(tkwin, pixmap, butPtr->highlightBorder, 0, 0, - Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); - } else { - Tk_Fill3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0, - Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); - } + if (butPtr->type == TYPE_BUTTON) { + Tk_Fill3DRectangle(tkwin, pixmap, butPtr->highlightBorder, 0, 0, + Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); + } else { + Tk_Fill3DRectangle(tkwin, pixmap, butPtr->normalBorder, 0, 0, + Tk_Width(tkwin), Tk_Height(tkwin), 0, TK_RELIEF_FLAT); + } } /* * Draw the native portion of the buttons. Start by creating the control - * if it doesn't already exist. Then configure the Macintosh control from - * the Tk info. Finally, we call Draw1Control to draw to the screen. + * if it doesn't already exist. Then configure the Macintosh control from + * the Tk info. Finally, we call Draw1Control to draw to the screen. */ if (macButtonPtr->usingControl) { - borderWidth = 0; - TkMacOSXDrawControl(macButtonPtr, destPort, dpPtr->gc, pixmap); - } else { - if (wasUsingControl && macButtonPtr->userPane) { - DisposeControl(macButtonPtr->userPane); - macButtonPtr->userPane = NULL; - macButtonPtr->control = NULL; - macButtonPtr->flags = 0; - } + borderWidth = 0; + TkMacOSXDrawControl(macButtonPtr, destPort, dpPtr->gc, pixmap); + } else if (wasUsingControl && macButtonPtr->userPane) { + DisposeControl(macButtonPtr->userPane); + macButtonPtr->userPane = NULL; + macButtonPtr->control = NULL; + macButtonPtr->flags = 0; } if ((dpPtr->drawType == DRAW_CUSTOM) || (dpPtr->drawType == DRAW_LABEL)) { - borderWidth = butPtr->borderWidth; + borderWidth = butPtr->borderWidth; } /* - * Display image or bitmap or text for button. This has + * Display image or bitmap or text for button. This has * already been done under Appearance with the Bevel * button types. */ if (dpPtr->drawType == DRAW_BEVEL) { - /* Empty Body */ - } else { - if (butPtr->image != None) { - Tk_SizeOfImage(butPtr->image, &width, &height); - haveImage = 1; - } else if (butPtr->bitmap != None) { - Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); - haveImage = 1; - } - imageWidth = width; - imageHeight = height; - - haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0); - if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) { - int x; - int y; - textXOffset = 0; - textYOffset = 0; - fullWidth = 0; - fullHeight = 0; - - switch ((enum compound) butPtr->compound) { - case COMPOUND_TOP: - case COMPOUND_BOTTOM: { - /* Image is above or below text */ - if (butPtr->compound == COMPOUND_TOP) { - textYOffset = height + butPtr->padY; - } else { - imageYOffset = butPtr->textHeight + butPtr->padY; - } - fullHeight = height + butPtr->textHeight + butPtr->padY; - fullWidth = (width > butPtr->textWidth ? width : - butPtr->textWidth); - textXOffset = (fullWidth - butPtr->textWidth)/2; - imageXOffset = (fullWidth - width)/2; - break; - } - case COMPOUND_LEFT: - case COMPOUND_RIGHT: { - /* - * Image is left or right of text - */ - - if (butPtr->compound == COMPOUND_LEFT) { - textXOffset = width + butPtr->padX; - } else { - imageXOffset = butPtr->textWidth + butPtr->padX; - } - fullWidth = butPtr->textWidth + butPtr->padX + width; - fullHeight = (height > butPtr->textHeight ? height : - butPtr->textHeight); - textYOffset = (fullHeight - butPtr->textHeight)/2; - imageYOffset = (fullHeight - height)/2; - break; - } - case COMPOUND_CENTER: { - /* - * Image and text are superimposed - */ - - fullWidth = (width > butPtr->textWidth ? width : - butPtr->textWidth); - fullHeight = (height > butPtr->textHeight ? height : - butPtr->textHeight); - textXOffset = (fullWidth - butPtr->textWidth)/2; - imageXOffset = (fullWidth - width)/2; - textYOffset = (fullHeight - butPtr->textHeight)/2; - imageYOffset = (fullHeight - height)/2; - break; - } - case COMPOUND_NONE: {break;} - } - - TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY, - butPtr->indicatorSpace + fullWidth, fullHeight, &x, &y); - - x += butPtr->indicatorSpace; - - x += dpPtr->offset; - y += dpPtr->offset; - if (dpPtr->relief == TK_RELIEF_RAISED) { - x -= dpPtr->offset; - y -= dpPtr->offset; - } else if (dpPtr->relief == TK_RELIEF_SUNKEN) { - x += dpPtr->offset; - y += dpPtr->offset; - } - imageXOffset += x; - imageYOffset += y; - if (butPtr->image != NULL) { - if ((butPtr->selectImage != NULL) && - (butPtr->flags & SELECTED)) { - Tk_RedrawImage(butPtr->selectImage, 0, 0, - width, height, pixmap, imageXOffset, imageYOffset); - } else if ((butPtr->tristateImage != NULL) && - (butPtr->flags & TRISTATED)) { - Tk_RedrawImage(butPtr->tristateImage, 0, 0, - width, height, pixmap, imageXOffset, imageYOffset); - } else { - Tk_RedrawImage(butPtr->image, 0, 0, width, - height, pixmap, imageXOffset, imageYOffset); - } - } else { - XSetClipOrigin(butPtr->display, dpPtr->gc, - imageXOffset, imageYOffset); - XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc, - 0, 0, (unsigned int) width, (unsigned int) height, - imageXOffset, imageYOffset, 1); - XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0); - } - - if (macButtonPtr->useTkText) { - Tk_DrawTextLayout(butPtr->display, pixmap, - dpPtr->gc, butPtr->textLayout, - x + textXOffset, y + textYOffset, 0, -1); - Tk_UnderlineTextLayout(butPtr->display, pixmap, dpPtr->gc, - butPtr->textLayout, - x + textXOffset, y + textYOffset, - butPtr->underline); - } - y += fullHeight/2; - } else { - if (haveImage) { - int x = 0; - int y; - - TkComputeAnchor(butPtr->anchor, tkwin, 0, 0, - butPtr->indicatorSpace + width, height, &x, &y); - x += butPtr->indicatorSpace; - - x += dpPtr->offset; - y += dpPtr->offset; - if (dpPtr->relief == TK_RELIEF_RAISED) { - x -= dpPtr->offset; - y -= dpPtr->offset; - } else if (dpPtr->relief == TK_RELIEF_SUNKEN) { - x += dpPtr->offset; - y += dpPtr->offset; - } - imageXOffset += x; - imageYOffset += y; - if (butPtr->image != NULL) { - if ((butPtr->selectImage != NULL) && - (butPtr->flags & SELECTED)) { - Tk_RedrawImage(butPtr->selectImage, 0, 0, width, - height, pixmap, imageXOffset, imageYOffset); - } else if ((butPtr->tristateImage != NULL) && - (butPtr->flags & TRISTATED)) { - Tk_RedrawImage(butPtr->tristateImage, 0, 0, width, - height, pixmap, imageXOffset, imageYOffset); - } else { - Tk_RedrawImage(butPtr->image, 0, 0, width, height, - pixmap, imageXOffset, imageYOffset); - } - } else { - XSetClipOrigin(butPtr->display, dpPtr->gc, x, y); - XCopyPlane(butPtr->display, butPtr->bitmap, - pixmap, dpPtr->gc, - 0, 0, (unsigned int) width, - (unsigned int) height, x, y, 1); - XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0); - } - y += height/2; - } else if (macButtonPtr->useTkText) { - int x = 0; - int y; - TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, - butPtr->padY, - butPtr->indicatorSpace + butPtr->textWidth, - butPtr->textHeight, &x, &y); - x += butPtr->indicatorSpace; - Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, - butPtr->textLayout, x, y, 0, -1); - } - } + goto applyStipple; + } + + if (butPtr->image != None) { + Tk_SizeOfImage(butPtr->image, &width, &height); + haveImage = 1; + } else if (butPtr->bitmap != None) { + Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); + haveImage = 1; + } + imageWidth = width; + imageHeight = height; + + haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0); + if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) { + int x, y; + + textXOffset = 0; + textYOffset = 0; + fullWidth = 0; + fullHeight = 0; + + switch ((enum compound) butPtr->compound) { + case COMPOUND_TOP: + case COMPOUND_BOTTOM: + /* + * Image is above or below text. + */ + if (butPtr->compound == COMPOUND_TOP) { + textYOffset = height + butPtr->padY; + } else { + imageYOffset = butPtr->textHeight + butPtr->padY; + } + fullHeight = height + butPtr->textHeight + butPtr->padY; + fullWidth = (width > butPtr->textWidth ? width : + butPtr->textWidth); + textXOffset = (fullWidth - butPtr->textWidth)/2; + imageXOffset = (fullWidth - width)/2; + break; + + case COMPOUND_LEFT: + case COMPOUND_RIGHT: + /* + * Image is left or right of text. + */ + + if (butPtr->compound == COMPOUND_LEFT) { + textXOffset = width + butPtr->padX; + } else { + imageXOffset = butPtr->textWidth + butPtr->padX; + } + fullWidth = butPtr->textWidth + butPtr->padX + width; + fullHeight = (height > butPtr->textHeight ? height : + butPtr->textHeight); + textYOffset = (fullHeight - butPtr->textHeight)/2; + imageYOffset = (fullHeight - height)/2; + break; + + case COMPOUND_CENTER: + /* + * Image and text are superimposed. + */ + + fullWidth = (width > butPtr->textWidth ? width : + butPtr->textWidth); + fullHeight = (height > butPtr->textHeight ? height : + butPtr->textHeight); + textXOffset = (fullWidth - butPtr->textWidth)/2; + imageXOffset = (fullWidth - width)/2; + textYOffset = (fullHeight - butPtr->textHeight)/2; + imageYOffset = (fullHeight - height)/2; + break; + + case COMPOUND_NONE: + break; + } + + TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY, + butPtr->indicatorSpace + fullWidth, fullHeight, &x, &y); + + x += butPtr->indicatorSpace; + + x += dpPtr->offset; + y += dpPtr->offset; + if (dpPtr->relief == TK_RELIEF_RAISED) { + x -= dpPtr->offset; + y -= dpPtr->offset; + } else if (dpPtr->relief == TK_RELIEF_SUNKEN) { + x += dpPtr->offset; + y += dpPtr->offset; + } + imageXOffset += x; + imageYOffset += y; + if (butPtr->image != NULL) { + if ((butPtr->selectImage != NULL) && (butPtr->flags & SELECTED)) { + Tk_RedrawImage(butPtr->selectImage, 0, 0, width, height, + pixmap, imageXOffset, imageYOffset); + } else if ((butPtr->tristateImage != NULL) && + (butPtr->flags & TRISTATED)) { + Tk_RedrawImage(butPtr->tristateImage, 0, 0, width, height, + pixmap, imageXOffset, imageYOffset); + } else { + Tk_RedrawImage(butPtr->image, 0, 0, width, height, + pixmap, imageXOffset, imageYOffset); + } + } else { + XSetClipOrigin(butPtr->display, dpPtr->gc, imageXOffset, + imageYOffset); + XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc, + 0, 0, width, height, imageXOffset, imageYOffset, 1); + XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0); + } + + if (macButtonPtr->useTkText) { + Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, + butPtr->textLayout, x + textXOffset, y + textYOffset, 0, + -1); + Tk_UnderlineTextLayout(butPtr->display, pixmap, dpPtr->gc, + butPtr->textLayout, x + textXOffset, y + textYOffset, + butPtr->underline); + } + y += fullHeight/2; + } else if (haveImage) { + int x = 0, y; + + TkComputeAnchor(butPtr->anchor, tkwin, 0, 0, + butPtr->indicatorSpace + width, height, &x, &y); + x += butPtr->indicatorSpace; + + x += dpPtr->offset; + y += dpPtr->offset; + if (dpPtr->relief == TK_RELIEF_RAISED) { + x -= dpPtr->offset; + y -= dpPtr->offset; + } else if (dpPtr->relief == TK_RELIEF_SUNKEN) { + x += dpPtr->offset; + y += dpPtr->offset; + } + imageXOffset += x; + imageYOffset += y; + if (butPtr->image != NULL) { + if ((butPtr->selectImage != NULL) && (butPtr->flags & SELECTED)) { + Tk_RedrawImage(butPtr->selectImage, 0, 0, width, height, + pixmap, imageXOffset, imageYOffset); + } else if ((butPtr->tristateImage != NULL) && + (butPtr->flags & TRISTATED)) { + Tk_RedrawImage(butPtr->tristateImage, 0, 0, width, height, + pixmap, imageXOffset, imageYOffset); + } else { + Tk_RedrawImage(butPtr->image, 0, 0, width, height, + pixmap, imageXOffset, imageYOffset); + } + } else { + XSetClipOrigin(butPtr->display, dpPtr->gc, x, y); + XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc, + 0, 0, width, height, x, y, 1); + XSetClipOrigin(butPtr->display, dpPtr->gc, 0, 0); + } + y += height/2; + } else if (macButtonPtr->useTkText) { + int x = 0, y; + + TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, butPtr->padY, + butPtr->indicatorSpace + butPtr->textWidth, + butPtr->textHeight, &x, &y); + x += butPtr->indicatorSpace; + Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, + butPtr->textLayout, x, y, 0, -1); } /* * If the button is disabled with a stipple rather than a special - * foreground color, generate the stippled effect. If the widget + * foreground color, generate the stippled effect. If the widget * is selected and we use a different background color when selected, * must temporarily modify the GC so the stippling is the right color. */ + applyStipple: if (macButtonPtr->useTkText) { - if ((butPtr->state == STATE_DISABLED) - && ((butPtr->disabledFg == NULL) || (butPtr->image != NULL))) { - if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn + if ((butPtr->state == STATE_DISABLED) + && ((butPtr->disabledFg == NULL) || (butPtr->image != NULL))) { + if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn && (butPtr->selectBorder != NULL)) { - XSetForeground(butPtr->display, butPtr->stippleGC, + XSetForeground(butPtr->display, butPtr->stippleGC, Tk_3DBorderColor(butPtr->selectBorder)->pixel); - } + } + /* * Stipple the whole button if no disabledFg was specified, * otherwise restrict stippling only to displayed image */ + if (butPtr->disabledFg == NULL) { XFillRectangle(butPtr->display, pixmap, butPtr->stippleGC, 0, 0, (unsigned) Tk_Width(tkwin), @@ -485,24 +476,28 @@ TkpDisplayButton( imageXOffset, imageYOffset, (unsigned) imageWidth, (unsigned) imageHeight); } - if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn + if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn && (butPtr->selectBorder != NULL)) { XSetForeground(butPtr->display, butPtr->stippleGC, Tk_3DBorderColor(butPtr->normalBorder)->pixel); } - } - - /* - * Draw the border and traversal highlight last. This way, if the - * button's contents overflow they'll be covered up by the border. - */ - - if (dpPtr->relief != TK_RELIEF_FLAT) { - int inset = butPtr->highlightWidth; - Tk_Draw3DRectangle(tkwin, pixmap, dpPtr->border, inset, inset, - Tk_Width(tkwin) - 2*inset, Tk_Height(tkwin) - 2*inset, - butPtr->borderWidth, dpPtr->relief); - } + } + + /* + * Draw the border and traversal highlight last. This way, if the + * button's contents overflow they'll be covered up by the border. + */ + + if (dpPtr->relief != TK_RELIEF_FLAT) { + int inset = butPtr->highlightWidth; + + Tk_Draw3DRectangle(tkwin, pixmap, dpPtr->border, inset, inset, + Tk_Width(tkwin) - 2*inset, Tk_Height(tkwin) - 2*inset, + butPtr->borderWidth, dpPtr->relief); + } + } + if (portChanged) { + QDSwapPort(savePort, NULL); } } @@ -511,60 +506,58 @@ TkpDisplayButton( * * TkpComputeButtonGeometry -- * - * After changes in a button's text or bitmap, this procedure - * recomputes the button's geometry and passes this information - * along to the geometry manager for the window. + * After changes in a button's text or bitmap, this procedure + * recomputes the button's geometry and passes this information + * along to the geometry manager for the window. * * Results: - * None. + * None. * * Side effects: - * The button's window may change size. + * The button's window may change size. * *---------------------------------------------------------------------- */ void TkpComputeButtonGeometry( - TkButton *butPtr) /* Button whose geometry may have changed. */ + TkButton *butPtr) /* Button whose geometry may have changed. */ { int width, height, avgWidth, haveImage = 0, haveText = 0; - int xInset, yInset; - int txtWidth, txtHeight; + int xInset, yInset, txtWidth, txtHeight; Tk_FontMetrics fm; DrawParams drawParams; /* * First figure out the size of the contents of the button. */ - + width = 0; height = 0; txtWidth = 0; txtHeight = 0; avgWidth = 0; - butPtr->indicatorSpace = 0; if (butPtr->image != NULL) { - Tk_SizeOfImage(butPtr->image, &width, &height); - haveImage = 1; + Tk_SizeOfImage(butPtr->image, &width, &height); + haveImage = 1; } else if (butPtr->bitmap != None) { - Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); - haveImage = 1; + Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); + haveImage = 1; } if (haveImage == 0 || butPtr->compound != COMPOUND_NONE) { - Tk_FreeTextLayout(butPtr->textLayout); - butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont, - Tcl_GetString(butPtr->textPtr), -1, butPtr->wrapLength, - butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight); - - txtWidth = butPtr->textWidth; - txtHeight = butPtr->textHeight; - avgWidth = Tk_TextWidth(butPtr->tkfont, "0", 1); - Tk_GetFontMetrics(butPtr->tkfont, &fm); - haveText = (txtWidth != 0 && txtHeight != 0); + Tk_FreeTextLayout(butPtr->textLayout); + butPtr->textLayout = Tk_ComputeTextLayout(butPtr->tkfont, + Tcl_GetString(butPtr->textPtr), -1, butPtr->wrapLength, + butPtr->justify, 0, &butPtr->textWidth, &butPtr->textHeight); + + txtWidth = butPtr->textWidth; + txtHeight = butPtr->textHeight; + avgWidth = Tk_TextWidth(butPtr->tkfont, "0", 1); + Tk_GetFontMetrics(butPtr->tkfont, &fm); + haveText = (txtWidth != 0 && txtHeight != 0); } /* @@ -575,172 +568,166 @@ TkpComputeButtonGeometry( */ if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) { - switch ((enum compound) butPtr->compound) { - case COMPOUND_TOP: - case COMPOUND_BOTTOM: { - /* - * Image is above or below text - */ - - height += txtHeight + butPtr->padY; - width = (width > txtWidth ? width : txtWidth); - break; - } - case COMPOUND_LEFT: - case COMPOUND_RIGHT: { - /* - * Image is left or right of text - */ - - width += txtWidth + butPtr->padX; - height = (height > txtHeight ? height : txtHeight); - break; - } - case COMPOUND_CENTER: { - /* - * Image and text are superimposed - */ - - width = (width > txtWidth ? width : txtWidth); - height = (height > txtHeight ? height : txtHeight); - break; - } - case COMPOUND_NONE: {break;} - } - if (butPtr->width > 0) { - width = butPtr->width; - } - if (butPtr->height > 0) { - height = butPtr->height; - } - - if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) { - butPtr->indicatorSpace = height; - if (butPtr->type == TYPE_CHECK_BUTTON) { - butPtr->indicatorDiameter = (65 * height)/100; - } else { - butPtr->indicatorDiameter = (75 * height)/100; - } - } - - width += 2 * butPtr->padX; - height += 2 * butPtr->padY; + switch ((enum compound) butPtr->compound) { + case COMPOUND_TOP: + case COMPOUND_BOTTOM: + /* + * Image is above or below text. + */ + + height += txtHeight + butPtr->padY; + width = (width > txtWidth ? width : txtWidth); + break; + case COMPOUND_LEFT: + case COMPOUND_RIGHT: + /* + * Image is left or right of text. + */ + + width += txtWidth + butPtr->padX; + height = (height > txtHeight ? height : txtHeight); + break; + case COMPOUND_CENTER: + /* + * Image and text are superimposed. + */ + + width = (width > txtWidth ? width : txtWidth); + height = (height > txtHeight ? height : txtHeight); + break; + case COMPOUND_NONE: + break; + } + if (butPtr->width > 0) { + width = butPtr->width; + } + if (butPtr->height > 0) { + height = butPtr->height; + } + if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) { + butPtr->indicatorSpace = height; + if (butPtr->type == TYPE_CHECK_BUTTON) { + butPtr->indicatorDiameter = (65 * height)/100; + } else { + butPtr->indicatorDiameter = (75 * height)/100; + } + } + + width += 2 * butPtr->padX; + height += 2 * butPtr->padY; + } else if (haveImage) { + if (butPtr->width > 0) { + width = butPtr->width; + } + if (butPtr->height > 0) { + height = butPtr->height; + } + if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) { + butPtr->indicatorSpace = height; + if (butPtr->type == TYPE_CHECK_BUTTON) { + butPtr->indicatorDiameter = (65 * height)/100; + } else { + butPtr->indicatorDiameter = (75 * height)/100; + } + } } else { - if (haveImage) { - if (butPtr->width > 0) { - width = butPtr->width; - } - if (butPtr->height > 0) { - height = butPtr->height; - } - if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) { - butPtr->indicatorSpace = height; - if (butPtr->type == TYPE_CHECK_BUTTON) { - butPtr->indicatorDiameter = (65 * height)/100; - } else { - butPtr->indicatorDiameter = (75 * height)/100; - } - } - } else { - width = txtWidth; - height = txtHeight; - if (butPtr->width > 0) { - width = butPtr->width * avgWidth; - } - if (butPtr->height > 0) { - height = butPtr->height * fm.linespace; - } - if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) { - butPtr->indicatorDiameter = fm.linespace; - if (butPtr->type == TYPE_CHECK_BUTTON) { - butPtr->indicatorDiameter = - (80 * butPtr->indicatorDiameter)/100; - } - butPtr->indicatorSpace = butPtr->indicatorDiameter + avgWidth; - } - } + width = txtWidth; + height = txtHeight; + if (butPtr->width > 0) { + width = butPtr->width * avgWidth; + } + if (butPtr->height > 0) { + height = butPtr->height * fm.linespace; + } + if ((butPtr->type >= TYPE_CHECK_BUTTON) && butPtr->indicatorOn) { + butPtr->indicatorDiameter = fm.linespace; + if (butPtr->type == TYPE_CHECK_BUTTON) { + butPtr->indicatorDiameter = + (80 * butPtr->indicatorDiameter)/100; + } + butPtr->indicatorSpace = butPtr->indicatorDiameter + avgWidth; + } } /* * Now figure out the size of the border decorations for the button. */ - + if (butPtr->highlightWidth < 0) { - butPtr->highlightWidth = 0; + butPtr->highlightWidth = 0; } - + /* - * The width and height calculation for Appearance buttons with images & - * non-Appearance buttons with images is different. In the latter case, + * The width and height calculation for Appearance buttons with images & + * non-Appearance buttons with images is different. In the latter case, * we add the borderwidth to the inset, since we are going to stamp a - * 3-D border over the image. In the former, we add it to the height, + * 3-D border over the image. In the former, we add it to the height, * directly, since Appearance will draw the border as part of our control. * * When issuing the geometry request, add extra space for the indicator, - * if any, and for the border and padding, plus if this is an image two + * if any, and for the border and padding, plus if this is an image two * extra pixels so the display can be offset by 1 pixel in either * direction for the raised or lowered effect. * * The highlight width corresponds to the default ring on the Macintosh. * As such, the highlight width is only added if the button is the default - * button. The actual width of the default ring is one less than the + * button. The actual width of the default ring is one less than the * highlight width as there is also one pixel of spacing. - * Appearance buttons with images do not have a highlight ring, because the + * Appearance buttons with images do not have a highlight ring, because the * Bevel button type does not support one. */ if ((butPtr->image == None) && (butPtr->bitmap == None)) { - width += 2*butPtr->padX; - height += 2*butPtr->padY; + width += 2*butPtr->padX; + height += 2*butPtr->padY; } - + if ((butPtr->type == TYPE_BUTTON)) { - if ((butPtr->image == None) && (butPtr->bitmap == None)) { - butPtr->inset = 0; - if (butPtr->defaultState != STATE_DISABLED) { - butPtr->inset += butPtr->highlightWidth; - } - } else { - butPtr->inset = 0; - width += (2 * butPtr->borderWidth + 4); - height += (2 * butPtr->borderWidth + 4); - } - } else if ((butPtr->type != TYPE_LABEL)) { - if (butPtr->indicatorOn) { - butPtr->inset = 0; - } else { - /* - * Under Appearance, the Checkbutton or radiobutton with an image - * is represented by a BevelButton with the Sticky defProc... - * So we must set its height in the same way as the Button - * with an image or bitmap. - */ - - if ( (butPtr->image != None) || (butPtr->bitmap != None)) { - int border; - butPtr->inset = 0; - if ( butPtr->borderWidth <= 2 ) { - border = 6; - } else { - border = 2 * butPtr->borderWidth + 2; - } - width += border; - height += border; - } else { - butPtr->inset = butPtr->borderWidth; - } - } + if ((butPtr->image == None) && (butPtr->bitmap == None)) { + butPtr->inset = 0; + if (butPtr->defaultState != STATE_DISABLED) { + butPtr->inset += butPtr->highlightWidth; + } + } else { + butPtr->inset = 0; + width += (2 * butPtr->borderWidth + 4); + height += (2 * butPtr->borderWidth + 4); + } + } else if (butPtr->type == TYPE_LABEL) { + butPtr->inset = butPtr->borderWidth; + } else if (butPtr->indicatorOn) { + butPtr->inset = 0; } else { - butPtr->inset = butPtr->borderWidth; + /* + * Under Appearance, the Checkbutton or radiobutton with an image + * is represented by a BevelButton with the Sticky defProc... + * So we must set its height in the same way as the Button + * with an image or bitmap. + */ + + if (butPtr->image != None || butPtr->bitmap != None) { + int border; + + butPtr->inset = 0; + if (butPtr->borderWidth <= 2) { + border = 6; + } else { + border = 2 * butPtr->borderWidth + 2; + } + width += border; + height += border; + } else { + butPtr->inset = butPtr->borderWidth; + } } if (TkMacOSXComputeDrawParams(butPtr,&drawParams)) { - xInset = butPtr->indicatorSpace + DEF_INSET_LEFT + DEF_INSET_RIGHT; - yInset = DEF_INSET_TOP + DEF_INSET_BOTTOM; + xInset = butPtr->indicatorSpace + DEF_INSET_LEFT + DEF_INSET_RIGHT; + yInset = DEF_INSET_TOP + DEF_INSET_BOTTOM; } else { - xInset = butPtr->indicatorSpace+butPtr->inset*2; - yInset = butPtr->inset*2; + xInset = butPtr->indicatorSpace+butPtr->inset*2; + yInset = butPtr->inset*2; } Tk_GeometryRequest(butPtr->tkwin, width + xInset, height + yInset); Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset); @@ -751,13 +738,13 @@ TkpComputeButtonGeometry( * * TkpDestroyButton -- * - * Free data structures associated with the button control. + * Free data structures associated with the button control. * * Results: - * None. + * None. * * Side effects: - * Restores the default control state. + * Restores the default control state. * *---------------------------------------------------------------------- */ @@ -766,10 +753,11 @@ void TkpDestroyButton( TkButton *butPtr) { - MacButton *mbPtr = ( MacButton *) butPtr; /* Mac button. */ + MacButton *mbPtr = (MacButton *) butPtr; /* Mac button. */ + if (mbPtr->userPane) { - DisposeControl(mbPtr->userPane); - mbPtr->userPane = NULL; + DisposeControl(mbPtr->userPane); + mbPtr->userPane = NULL; } } @@ -778,246 +766,214 @@ TkpDestroyButton( * * TkMacOSXInitControl -- * - * This procedure initialises a Carbon control + * This procedure initialises a Carbon control. * * Results: - * 0 on success, 1 on failure. + * 0 on success, 1 on failure. * * Side effects: - * A background pane control and the control itself is created - * The contol is embedded in the background control - * The background control is embedded in the root control - * of the containing window - * The creation parameters for the control are also computed + * A background pane control and the control itself is created + * The contol is embedded in the background control + * The background control is embedded in the root control + * of the containing window + * The creation parameters for the control are also computed * *---------------------------------------------------------------------- */ static int -TkMacOSXInitControl ( - MacButton *mbPtr, /* Mac button. */ - GWorldPtr destPort, - GC gc, - Pixmap pixmap, - Rect *paneRect, - Rect *cntrRect -) +TkMacOSXInitControl( + MacButton *mbPtr, /* Mac button. */ + GWorldPtr destPort, + GC gc, + Pixmap pixmap, + Rect *paneRect, + Rect *cntrRect) { - OSErr status; - TkButton * butPtr = ( TkButton * )mbPtr; + TkButton *butPtr = (TkButton *) mbPtr; ControlRef rootControl; - SInt16 procID; - Boolean initiallyVisible; - SInt16 initialValue; - SInt16 minValue; - SInt16 maxValue; - SInt32 controlReference; + SInt16 procID, initialValue, minValue, maxValue; + Boolean initiallyVisible; + SInt32 controlReference; rootControl = TkMacOSXGetRootControl(Tk_WindowId(butPtr->tkwin)); - mbPtr->windowRef - = GetWindowFromPort(TkMacOSXGetDrawablePort(Tk_WindowId(butPtr->tkwin))); + mbPtr->windowRef = GetWindowFromPort( + TkMacOSXGetDrawablePort(Tk_WindowId(butPtr->tkwin))); - /* - * Set up the user pane + /* + * Set up the user pane. */ initiallyVisible = false; - initialValue = kControlSupportsEmbedding|kControlHasSpecialBackground; - minValue = 0; - maxValue = 1; - procID = kControlUserPaneProc; + initialValue = kControlSupportsEmbedding|kControlHasSpecialBackground; + minValue = 0; + maxValue = 1; + procID = kControlUserPaneProc; controlReference = (SInt32)mbPtr; - mbPtr->userPane = NewControl(mbPtr->windowRef, - paneRect, "\p", - initiallyVisible, - initialValue, - minValue, - maxValue, - procID, - controlReference ); - + mbPtr->userPane = NewControl(mbPtr->windowRef, paneRect, "\p", + initiallyVisible, initialValue, minValue, maxValue, procID, + controlReference); + if (!mbPtr->userPane) { -#ifdef TK_MAC_DEBUG - fprintf(stderr,"Failed to create user pane control\n"); -#endif - return 1; + TkMacOSXDbgMsg("Failed to create user pane control"); + return 1; } - - if ((status = EmbedControl(mbPtr->userPane,rootControl)) != noErr) { -#ifdef TK_MAC_DEBUG - fprintf(stderr,"Failed to embed user pane control %d\n", status); -#endif - return 1; + if (ChkErr(EmbedControl, mbPtr->userPane,rootControl) != noErr) { + return 1; } - + SetUserPaneSetUpSpecialBackgroundProc(mbPtr->userPane, - UserPaneBackgroundProc); + UserPaneBackgroundProc); SetUserPaneDrawProc(mbPtr->userPane,UserPaneDraw); initiallyVisible = false; TkMacOSXComputeControlParams(butPtr,&mbPtr->params); - mbPtr->control = NewControl(mbPtr->windowRef, - cntrRect, "\p", - initiallyVisible, - mbPtr->params.initialValue, - mbPtr->params.minValue, - mbPtr->params.maxValue, - mbPtr->params.procID, - controlReference ); - + mbPtr->control = NewControl(mbPtr->windowRef, cntrRect, "\p", + initiallyVisible, mbPtr->params.initialValue, + mbPtr->params.minValue, mbPtr->params.maxValue, + mbPtr->params.procID, controlReference); + if (!mbPtr->control) { -#ifdef TK_MAC_DEBUG - fprintf(stderr,"failed to create control of type %d\n",procID); -#endif - return 1; + TkMacOSXDbgMsg("failed to create control of type %d\n", procID); + return 1; } - - if (EmbedControl(mbPtr->control,mbPtr->userPane) != noErr ) { -#ifdef TK_MAC_DEBUG - fprintf(stderr,"failed to embed control of type %d\n",procID); -#endif - return 1; + if (ChkErr(EmbedControl, mbPtr->control,mbPtr->userPane) != noErr ) { + return 1; } - + mbPtr->flags |= (1 + 2); return 0; } - + /* *-------------------------------------------------------------- * * TkMacOSXDrawControl -- * - * This function draws the tk button using Mac controls - * In addition, this code may apply custom colors passed - * in the TkButton. + * This function draws the tk button using Mac controls + * In addition, this code may apply custom colors passed + * in the TkButton. * * Results: - * None. + * None. * * Side effects: - * The control is created, or reinitialised as needed - * + * The control is created, or reinitialised as needed. * *-------------------------------------------------------------- */ static void TkMacOSXDrawControl( - MacButton *mbPtr, /* Mac button. */ - GWorldPtr destPort, /* Off screen GWorld. */ - GC gc, /* The GC we are drawing into - needed for - * the bevel button */ - Pixmap pixmap) /* The pixmap we are drawing into - needed - * for the bevel button */ - + MacButton *mbPtr, /* Mac button. */ + GWorldPtr destPort, /* Off screen GWorld. */ + GC gc, /* The GC we are drawing into - needed for the + * bevel button */ + Pixmap pixmap) /* The pixmap we are drawing into - needed for + * the bevel button */ { - TkButton * butPtr = ( TkButton *)mbPtr; - int err; - TkWindow * winPtr; - Rect paneRect; - Rect cntrRect; - - winPtr = (TkWindow *)butPtr->tkwin; - - paneRect.left = winPtr->privatePtr->xOff; - paneRect.top = winPtr->privatePtr->yOff; - paneRect.right = paneRect.left + Tk_Width(butPtr->tkwin); + TkButton *butPtr = (TkButton *) mbPtr; + TkWindow *winPtr; + Rect paneRect, cntrRect; + + winPtr = (TkWindow *) butPtr->tkwin; + + paneRect.left = winPtr->privatePtr->xOff; + paneRect.top = winPtr->privatePtr->yOff; + paneRect.right = paneRect.left + Tk_Width(butPtr->tkwin); paneRect.bottom = paneRect.top + Tk_Height(butPtr->tkwin); cntrRect = paneRect; /* - cntrRect.left += butPtr->inset; - cntrRect.top += butPtr->inset; - cntrRect.right -= butPtr->inset; + cntrRect.left += butPtr->inset; + cntrRect.top += butPtr->inset; + cntrRect.right -= butPtr->inset; cntrRect.bottom -= butPtr->inset; */ - cntrRect.left += DEF_INSET_LEFT; - cntrRect.top += DEF_INSET_TOP; - cntrRect.right -= DEF_INSET_RIGHT; + cntrRect.left += DEF_INSET_LEFT; + cntrRect.top += DEF_INSET_TOP; + cntrRect.right -= DEF_INSET_RIGHT; cntrRect.bottom -= DEF_INSET_BOTTOM; - /* - * The control has been previously initialised - * It may need to be re-initialised + /* + * The control has been previously initialised. + * It may need to be re-initialised */ - + if (mbPtr->flags) { - MacControlParams params; - TkMacOSXComputeControlParams(butPtr, ¶ms); - if (bcmp(¶ms, &mbPtr->params, sizeof(params))) { - /* - * the type of control has changed - * Clean it up and clear the flag - */ - - if (mbPtr->userPane) { - DisposeControl(mbPtr->userPane); - mbPtr->userPane = NULL; - mbPtr->control = NULL; - } - mbPtr->flags = 0; - } + MacControlParams params; + + TkMacOSXComputeControlParams(butPtr, ¶ms); + if (bcmp(¶ms, &mbPtr->params, sizeof(params))) { + /* + * The type of control has changed. + * Clean it up and clear the flag. + */ + + if (mbPtr->userPane) { + DisposeControl(mbPtr->userPane); + mbPtr->userPane = NULL; + mbPtr->control = NULL; + } + mbPtr->flags = 0; + } } if (!(mbPtr->flags & 1)) { - if (TkMacOSXInitControl(mbPtr, destPort, gc, - pixmap, &paneRect, &cntrRect) ) { - return; - } + if (TkMacOSXInitControl(mbPtr, destPort, gc, pixmap, &paneRect, + &cntrRect)) { + return; + } } SetControlBounds(mbPtr->userPane, &paneRect); SetControlBounds(mbPtr->control, &cntrRect); if (!mbPtr->useTkText) { - Str255 controlTitle; - ControlFontStyleRec fontStyle; - Tk_Font font; - int len; - - if (((mbPtr->info.image == NULL) && (mbPtr->info.bitmap == None)) - || (mbPtr->info.compound != COMPOUND_NONE)) { - len = TkFontGetFirstTextLayout(butPtr->textLayout, - &font, (char*) controlTitle); - controlTitle[len] = 0; - } else { - len = 0; - controlTitle[0] = 0; - } - if (bcmp(mbPtr->controlTitle, controlTitle, len+1)) { - CFStringRef cf; - cf = CFStringCreateWithCString(NULL, - (char*) controlTitle, kCFStringEncodingUTF8); - if (cf != NULL) { - SetControlTitleWithCFString(mbPtr->control, cf); - CFRelease(cf); - } - bcopy(controlTitle, mbPtr->controlTitle, len+1); - } - if (len) { - TkMacOSXInitControlFontStyle(font, &fontStyle); - if (bcmp(&mbPtr->fontStyle, &fontStyle, sizeof(fontStyle)) ) { - if (SetControlFontStyle(mbPtr->control, &fontStyle) != noErr) { -#ifdef TK_MAC_DEBUG - fprintf(stderr,"SetControlFontStyle failed\n"); -#endif - } - bcopy(&fontStyle, &mbPtr->fontStyle, - sizeof(fontStyle)); - } - } + Str255 controlTitle; + ControlFontStyleRec fontStyle; + Tk_Font font; + int len; + + if (((mbPtr->info.image == NULL) && (mbPtr->info.bitmap == None)) + || (mbPtr->info.compound != COMPOUND_NONE)) { + len = TkFontGetFirstTextLayout(butPtr->textLayout, + &font, (char*) controlTitle); + controlTitle[len] = 0; + } else { + len = 0; + controlTitle[0] = 0; + } + if (bcmp(mbPtr->controlTitle, controlTitle, len+1)) { + CFStringRef cf = CFStringCreateWithCString(NULL, + (char*) controlTitle, kCFStringEncodingUTF8); + + if (cf != NULL) { + SetControlTitleWithCFString(mbPtr->control, cf); + CFRelease(cf); + } + bcopy(controlTitle, mbPtr->controlTitle, len+1); + } + if (len) { + TkMacOSXInitControlFontStyle(font, &fontStyle); + if (bcmp(&mbPtr->fontStyle, &fontStyle, sizeof(fontStyle)) ) { + ChkErr(SetControlFontStyle, mbPtr->control, &fontStyle); + bcopy(&fontStyle, &mbPtr->fontStyle, sizeof(fontStyle)); + } + } } if (mbPtr->params.isBevel) { - /* Initialiase the image/button parameters */ - SetupBevelButton(mbPtr, mbPtr->control, destPort, - gc, pixmap); + /* + * Initialiase the image/button parameters. + */ + + SetupBevelButton(mbPtr, mbPtr->control, destPort, gc, pixmap); } if (butPtr->flags & SELECTED) { - SetControlValue(mbPtr->control, 1); + SetControlValue(mbPtr->control, 1); } else if (butPtr->flags & TRISTATED) { - SetControlValue(mbPtr->control, 2); + SetControlValue(mbPtr->control, 2); } else { - SetControlValue(mbPtr->control, 0); + SetControlValue(mbPtr->control, 0); } if (!Tk_MacOSXIsAppInFront() || butPtr->state == STATE_DISABLED) { @@ -1027,6 +983,7 @@ TkMacOSXDrawControl( * Use NoPart for normal and to ensure correct direct transition from * disabled to active -state. [Bug 706446] */ + HiliteControl(mbPtr->control, kControlNoPart); if (butPtr->state == STATE_ACTIVE) { @@ -1035,7 +992,7 @@ TkMacOSXDrawControl( } else { switch (butPtr->type) { case TYPE_BUTTON: - HiliteControl(mbPtr->control, kControlButtonPart); + HiliteControl(mbPtr->control, kControlButtonPart); break; case TYPE_RADIO_BUTTON: HiliteControl(mbPtr->control, kControlRadioButtonPart); @@ -1050,30 +1007,28 @@ TkMacOSXDrawControl( UpdateControlColors(mbPtr); if (butPtr->type == TYPE_BUTTON) { - Boolean isDefault; - - if (butPtr->defaultState == STATE_ACTIVE) { - isDefault = true; - } else { - isDefault = false; - } - if ((err=SetControlData(mbPtr->control, kControlNoPart, - kControlPushButtonDefaultTag, - sizeof(isDefault), (Ptr) &isDefault)) != noErr) { - } + Boolean isDefault; + + if (butPtr->defaultState == STATE_ACTIVE) { + isDefault = true; + } else { + isDefault = false; + } + ChkErr(SetControlData, mbPtr->control, kControlNoPart, + kControlPushButtonDefaultTag, sizeof(isDefault), &isDefault); } - if (mbPtr->flags&2) { - ShowControl(mbPtr->userPane); - ShowControl(mbPtr->control); - mbPtr->flags ^= 2; + if (mbPtr->flags & 2) { + ShowControl(mbPtr->userPane); + ShowControl(mbPtr->control); + mbPtr->flags ^= 2; } else { - SetControlVisibility(mbPtr->control, true, true); - Draw1Control(mbPtr->userPane); + SetControlVisibility(mbPtr->control, true, true); + Draw1Control(mbPtr->userPane); } if (mbPtr->params.isBevel) { - KillPicture(mbPtr->bevelButtonContent.u.picture); + KillPicture(mbPtr->bevelButtonContent.u.picture); } } @@ -1082,150 +1037,131 @@ TkMacOSXDrawControl( * * SetupBevelButton -- * - * Sets up the Bevel Button with image by copying the - * source image onto the PicHandle for the button. + * Sets up the Bevel Button with image by copying the + * source image onto the PicHandle for the button. * * Results: - * None + * None * * Side effects: - * The image or bitmap for the button is copied over to a picture. + * The image or bitmap for the button is copied over to a picture. * *-------------------------------------------------------------- */ + void SetupBevelButton( - MacButton *mbPtr, /* Mac button. */ - ControlRef controlHandle, /* The control to set this picture to */ - GWorldPtr destPort, /* Off screen GWorld. */ - GC gc, /* The GC we are drawing into - needed for - * the bevel button */ - Pixmap pixmap /* The pixmap we are drawing into - needed - for the bevel button */ - ) + MacButton *mbPtr, /* Mac button. */ + ControlRef controlHandle, /* The control to set this picture to. */ + GWorldPtr destPort, /* Off screen GWorld. */ + GC gc, /* The GC we are drawing into - needed for the + * bevel button. */ + Pixmap pixmap) /* The pixmap we are drawing into - needed for + * the bevel button. */ { - int err; - TkButton *butPtr = ( TkButton *)mbPtr; + TkButton *butPtr = (TkButton *) mbPtr; int height, width; ControlButtonGraphicAlignment theAlignment; - - SetPort(destPort); + CGrafPtr savePort; + Boolean portChanged; + + portChanged = QDSwapPort(destPort, &savePort); if (butPtr->image != None) { - Tk_SizeOfImage(butPtr->image, - &width, &height); + Tk_SizeOfImage(butPtr->image, &width, &height); } else { - Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, - &width, &height); + Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); } - + if ((butPtr->width > 0) && (butPtr->width < width)) { - width = butPtr->width; + width = butPtr->width; } if ((butPtr->height > 0) && (butPtr->height < height)) { - height = butPtr->height; + height = butPtr->height; } mbPtr->picParams.srcRect.right = width; mbPtr->picParams.srcRect.bottom = height; - /* - * Set the flag to circumvent clipping and bounds problems with OS 10.0.4 + /* + * Set the flag to circumvent clipping and bounds problems with OS 10.0.4 */ - - if (!(mbPtr->bevelButtonContent.u.picture - = OpenCPicture(&mbPtr->picParams)) ) { -#ifdef TK_MAC_DEBUG - fprintf(stderr,"OpenCPicture failed\n"); -#endif + + mbPtr->bevelButtonContent.u.picture = OpenCPicture(&mbPtr->picParams); + if (!mbPtr->bevelButtonContent.u.picture) { + TkMacOSXDbgMsg("OpenCPicture failed"); } tkPictureIsOpen = 1; - + /* * TO DO - There is one case where XCopyPlane calls CopyDeepMask, - * which does not get recorded in the picture. So the bitmap code + * which does not get recorded in the picture. So the bitmap code * will fail in that case. */ - - if ((butPtr->selectImage != NULL) && (butPtr->flags & SELECTED)) { - Tk_RedrawImage(butPtr->selectImage, 0, 0, width, height, - pixmap, 0, 0); - } else if ((butPtr->tristateImage != NULL) && (butPtr->flags & TRISTATED)) { - Tk_RedrawImage(butPtr->tristateImage, 0, 0, width, height, - pixmap, 0, 0); + + if (butPtr->selectImage != NULL && (butPtr->flags & SELECTED)) { + Tk_RedrawImage(butPtr->selectImage, 0, 0, width, height, pixmap, 0, 0); + } else if (butPtr->tristateImage != NULL && (butPtr->flags & TRISTATED)) { + Tk_RedrawImage(butPtr->tristateImage, 0, 0, width, height, pixmap, 0, + 0); } else if (butPtr->image != NULL) { - Tk_RedrawImage(butPtr->image, 0, 0, width, - height, pixmap, 0, 0); - } else { - XSetClipOrigin(butPtr->display, gc, 0, 0); - XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, gc, 0, 0, - (unsigned int) width, (unsigned int) height, 0, 0, 1); + Tk_RedrawImage(butPtr->image, 0, 0, width, height, pixmap, 0, 0); + } else { + XSetClipOrigin(butPtr->display, gc, 0, 0); + XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, gc, 0, 0, width, + height, 0, 0, 1); } - + ClosePicture(); tkPictureIsOpen = 0; - - if ((err = SetControlData(controlHandle, kControlButtonPart, - kControlBevelButtonContentTag, - sizeof(ControlButtonContentInfo), - (char *) &mbPtr->bevelButtonContent)) != noErr) { -#ifdef TK_MAC_DEBUG - fprintf(stderr, - "SetControlData BevelButtonContent failed, %d\n", err ); -#endif - } - + + ChkErr(SetControlData, controlHandle, kControlButtonPart, + kControlBevelButtonContentTag, sizeof(ControlButtonContentInfo), + (char *) &mbPtr->bevelButtonContent); + if (butPtr->anchor == TK_ANCHOR_N) { - theAlignment = kControlBevelButtonAlignTop; - } else if (butPtr->anchor == TK_ANCHOR_NE) { - theAlignment = kControlBevelButtonAlignTopRight; - } else if (butPtr->anchor == TK_ANCHOR_E) { - theAlignment = kControlBevelButtonAlignRight; + theAlignment = kControlBevelButtonAlignTop; + } else if (butPtr->anchor == TK_ANCHOR_NE) { + theAlignment = kControlBevelButtonAlignTopRight; + } else if (butPtr->anchor == TK_ANCHOR_E) { + theAlignment = kControlBevelButtonAlignRight; } else if (butPtr->anchor == TK_ANCHOR_SE) { - theAlignment = kControlBevelButtonAlignBottomRight; + theAlignment = kControlBevelButtonAlignBottomRight; } else if (butPtr->anchor == TK_ANCHOR_S) { - theAlignment = kControlBevelButtonAlignBottom; + theAlignment = kControlBevelButtonAlignBottom; } else if (butPtr->anchor == TK_ANCHOR_SW) { - theAlignment = kControlBevelButtonAlignBottomLeft; + theAlignment = kControlBevelButtonAlignBottomLeft; } else if (butPtr->anchor == TK_ANCHOR_W) { - theAlignment = kControlBevelButtonAlignLeft; + theAlignment = kControlBevelButtonAlignLeft; } else if (butPtr->anchor == TK_ANCHOR_NW) { - theAlignment = kControlBevelButtonAlignTopLeft; + theAlignment = kControlBevelButtonAlignTopLeft; } else if (butPtr->anchor == TK_ANCHOR_CENTER) { - theAlignment = kControlBevelButtonAlignCenter; + theAlignment = kControlBevelButtonAlignCenter; } - if ((err = SetControlData(controlHandle, kControlButtonPart, - kControlBevelButtonGraphicAlignTag, - sizeof(ControlButtonGraphicAlignment), - (char *) &theAlignment)) != noErr) { -#ifdef TK_MAC_DEBUG - fprintf(stderr, - "SetControlData BevelButtonGraphicAlign failed, %d\n", err ); -#endif - } + ChkErr(SetControlData, controlHandle, kControlButtonPart, + kControlBevelButtonGraphicAlignTag, + sizeof(ControlButtonGraphicAlignment), (char *) &theAlignment); if (butPtr->compound != COMPOUND_NONE) { - ControlButtonTextPlacement thePlacement = \ - kControlBevelButtonPlaceNormally; - if (butPtr->compound == COMPOUND_TOP) { - thePlacement = kControlBevelButtonPlaceBelowGraphic; - } else if (butPtr->compound == COMPOUND_BOTTOM) { - thePlacement = kControlBevelButtonPlaceAboveGraphic; - } else if (butPtr->compound == COMPOUND_LEFT) { - thePlacement = kControlBevelButtonPlaceToRightOfGraphic; - } else if (butPtr->compound == COMPOUND_RIGHT) { - thePlacement = kControlBevelButtonPlaceToLeftOfGraphic; - } - if ((err = SetControlData(controlHandle, kControlButtonPart, - kControlBevelButtonTextPlaceTag, - sizeof(ControlButtonTextPlacement), - (char *) &thePlacement)) != noErr) { -#ifdef TK_MAC_DEBUG - fprintf(stderr, - "SetControlData BevelButtonTextPlace failed, %d\n", err ); -#endif - } + ControlButtonTextPlacement thePlacement = + kControlBevelButtonPlaceNormally; + + if (butPtr->compound == COMPOUND_TOP) { + thePlacement = kControlBevelButtonPlaceBelowGraphic; + } else if (butPtr->compound == COMPOUND_BOTTOM) { + thePlacement = kControlBevelButtonPlaceAboveGraphic; + } else if (butPtr->compound == COMPOUND_LEFT) { + thePlacement = kControlBevelButtonPlaceToRightOfGraphic; + } else if (butPtr->compound == COMPOUND_RIGHT) { + thePlacement = kControlBevelButtonPlaceToLeftOfGraphic; + } + ChkErr(SetControlData, controlHandle, kControlButtonPart, + kControlBevelButtonTextPlaceTag, + sizeof(ControlButtonTextPlacement), (char *) &thePlacement); + } + if (portChanged) { + QDSwapPort(savePort, NULL); } } @@ -1234,28 +1170,30 @@ SetupBevelButton( * * SetUserPaneDrawProc -- * - * Utility function to add a UserPaneDrawProc - * to a userPane control. From MoreControls code - * from Apple DTS. + * Utility function to add a UserPaneDrawProc + * to a userPane control. From MoreControls code + * from Apple DTS. * * Results: - * MacOS system error. + * MacOS system error. * * Side effects: - * The user pane gets a new UserPaneDrawProc. + * The user pane gets a new UserPaneDrawProc. * *-------------------------------------------------------------- */ -OSErr SetUserPaneDrawProc ( + +OSStatus +SetUserPaneDrawProc( ControlRef control, ControlUserPaneDrawProcPtr upp) { ControlUserPaneDrawUPP myControlUserPaneDrawUPP; - myControlUserPaneDrawUPP = NewControlUserPaneDrawUPP(upp); - return SetControlData (control, - kControlNoPart, kControlUserPaneDrawProcTag, - sizeof(myControlUserPaneDrawUPP), - (Ptr) &myControlUserPaneDrawUPP); + + myControlUserPaneDrawUPP = NewControlUserPaneDrawUPP(upp); + return SetControlData(control, kControlNoPart, + kControlUserPaneDrawProcTag, sizeof(myControlUserPaneDrawUPP), + (Ptr) &myControlUserPaneDrawUPP); } /* @@ -1263,28 +1201,30 @@ OSErr SetUserPaneDrawProc ( * * SetUserPaneSetUpSpecialBackgroundProc -- * - * Utility function to add a UserPaneBackgroundProc - * to a userPane control + * Utility function to add a UserPaneBackgroundProc + * to a userPane control * * Results: - * MacOS system error. + * MacOS system error. * * Side effects: - * The user pane gets a new UserPaneBackgroundProc. + * The user pane gets a new UserPaneBackgroundProc. * *-------------------------------------------------------------- */ -OSErr + +OSStatus SetUserPaneSetUpSpecialBackgroundProc( - ControlRef control, + ControlRef control, ControlUserPaneBackgroundProcPtr upp) { ControlUserPaneBackgroundUPP myControlUserPaneBackgroundUPP; + myControlUserPaneBackgroundUPP = NewControlUserPaneBackgroundUPP(upp); - return SetControlData (control, kControlNoPart, - kControlUserPaneBackgroundProcTag, - sizeof(myControlUserPaneBackgroundUPP), - (Ptr) &myControlUserPaneBackgroundUPP); + return SetControlData(control, kControlNoPart, + kControlUserPaneBackgroundProcTag, + sizeof(myControlUserPaneBackgroundUPP), + (Ptr) &myControlUserPaneBackgroundUPP); } /* @@ -1292,28 +1232,29 @@ SetUserPaneSetUpSpecialBackgroundProc( * * UserPaneDraw -- * - * This function draws the background of the user pane that will - * lie under checkboxes and radiobuttons. + * This function draws the background of the user pane that will + * lie under checkboxes and radiobuttons. * * Results: - * None. + * None. * * Side effects: - * The user pane gets updated to the current color. + * The user pane gets updated to the current color. * *-------------------------------------------------------------- */ + void UserPaneDraw( ControlRef control, ControlPartCode cpc) { + MacButton *mbPtr = (MacButton *)(intptr_t)GetControlReference(control); Rect contrlRect; - MacButton * mbPtr; - mbPtr = ( MacButton *)GetControlReference(control); + GetControlBounds(control,&contrlRect); - RGBBackColor (&mbPtr->userPaneBackground); - EraseRect (&contrlRect); + TkMacOSXSetColorInPort(mbPtr->userPaneBackground, 0, NULL); + EraseRect(&contrlRect); } /* @@ -1321,14 +1262,14 @@ UserPaneDraw( * * UserPaneBackgroundProc -- * - * This function sets up the background of the user pane that will - * lie under checkboxes and radiobuttons. + * This function sets up the background of the user pane that will + * lie under checkboxes and radiobuttons. * * Results: - * None. + * None. * * Side effects: - * The user pane background gets set to the current color. + * The user pane background gets set to the current color. * *-------------------------------------------------------------- */ @@ -1338,10 +1279,10 @@ UserPaneBackgroundProc( ControlHandle control, ControlBackgroundPtr info) { - MacButton * mbPtr; - mbPtr = ( MacButton *)GetControlReference(control); + MacButton * mbPtr = (MacButton *)(intptr_t)GetControlReference(control); + if (info->colorDevice) { - RGBBackColor (&mbPtr->userPaneBackground); + TkMacOSXSetColorInPort(mbPtr->userPaneBackground, 0, NULL); } } @@ -1350,82 +1291,84 @@ UserPaneBackgroundProc( * * UpdateControlColors -- * - * This function will review the colors used to display - * a Macintosh button. If any non-standard colors are - * used we create a custom palette for the button, populate - * with the colors for the button and install the palette. + * This function will review the colors used to display + * a Macintosh button. If any non-standard colors are + * used we create a custom palette for the button, populate + * with the colors for the button and install the palette. * - * Under Appearance, we just set the pointer that will be - * used by the UserPaneDrawProc. + * Under Appearance, we just set the pointer that will be + * used by the UserPaneDrawProc. * * Results: - * None. + * None. * * Side effects: - * The Macintosh control may get a custom palette installed. + * The Macintosh control may get a custom palette installed. * *-------------------------------------------------------------- */ static int -UpdateControlColors(MacButton * mbPtr) +UpdateControlColors( + MacButton *mbPtr) { XColor *xcolor; - TkButton * butPtr = ( TkButton * )mbPtr; - + TkButton *butPtr = (TkButton *) mbPtr; + /* * Under Appearance we cannot change the background of the - * button itself. However, the color we are setting is the color - * of the containing userPane. This will be the color that peeks - * around the rounded corners of the button. + * button itself. However, the color we are setting is the color + * of the containing userPane. This will be the color that peeks + * around the rounded corners of the button. * We make this the highlightbackground rather than the background, * because if you color the background of a frame containing a * button, you usually also color the highlightbackground as well, * or you will get a thin grey ring around the button. */ - + if (butPtr->type == TYPE_BUTTON) { - xcolor = Tk_3DBorderColor(butPtr->highlightBorder); + xcolor = Tk_3DBorderColor(butPtr->highlightBorder); } else { - xcolor = Tk_3DBorderColor(butPtr->normalBorder); + xcolor = Tk_3DBorderColor(butPtr->normalBorder); } - TkSetMacColor(xcolor->pixel, &mbPtr->userPaneBackground); - + mbPtr->userPaneBackground = xcolor->pixel; + return false; -} +} + /* *-------------------------------------------------------------- * * ButtonEventProc -- * - * This procedure is invoked by the Tk dispatcher for various - * events on buttons. + * This procedure is invoked by the Tk dispatcher for various + * events on buttons. * * Results: - * None. + * None. * * Side effects: - * When it gets exposed, it is redisplayed. + * When it gets exposed, it is redisplayed. * *-------------------------------------------------------------- */ static void ButtonEventProc( - ClientData clientData, /* Information about window. */ - XEvent *eventPtr) /* Information about event. */ + ClientData clientData, /* Information about window. */ + XEvent *eventPtr) /* Information about event. */ { TkButton *buttonPtr = (TkButton *) clientData; + if (eventPtr->type == ActivateNotify - || eventPtr->type == DeactivateNotify) { - if ((buttonPtr->tkwin == NULL) - || (!Tk_IsMapped(buttonPtr->tkwin))) { - return; - } - if ((buttonPtr->flags & REDRAW_PENDING) == 0) { - Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) buttonPtr); - buttonPtr->flags |= REDRAW_PENDING; - } + || eventPtr->type == DeactivateNotify) { + if ((buttonPtr->tkwin == NULL) || (!Tk_IsMapped(buttonPtr->tkwin))) { + return; + } + if ((buttonPtr->flags & REDRAW_PENDING) == 0) { + Tcl_DoWhenIdle(TkpDisplayButton, (ClientData) buttonPtr); + buttonPtr->flags |= REDRAW_PENDING; + } } } @@ -1434,143 +1377,141 @@ ButtonEventProc( * * TkMacOSXComputeControlParams -- * - * This procedure computes the various parameters used - * when creating a Carbon control (NewControl) - * These are determined by the various tk button parameters + * This procedure computes the various parameters used + * when creating a Carbon control (NewControl). + * These are determined by the various tk button parameters * * Results: - * None. + * None. * * Side effects: - * Sets the control initialisation parameters + * Sets the control initialisation parameters * *---------------------------------------------------------------------- */ static void -TkMacOSXComputeControlParams(TkButton * butPtr, MacControlParams * paramsPtr ) +TkMacOSXComputeControlParams( + TkButton *butPtr, + MacControlParams *paramsPtr) { paramsPtr->isBevel = 0; - - /* - * Determine ProcID based on button type and dimensions + + /* + * Determine ProcID based on button type and dimensions. */ - + switch (butPtr->type) { - case TYPE_BUTTON: - if ((butPtr->image == None) && (butPtr->bitmap == None)) { - paramsPtr->initialValue = 1; - paramsPtr->minValue = 0; - paramsPtr->maxValue = 1; - paramsPtr->procID = kControlPushButtonProc; - } else { - paramsPtr->initialValue = 0; - paramsPtr->minValue = kControlBehaviorOffsetContents - | kControlContentPictHandle; - paramsPtr->maxValue = 1; - if (butPtr->borderWidth <= 2) { - paramsPtr->procID = kControlBevelButtonSmallBevelProc; - } else if (butPtr->borderWidth == 3) { - paramsPtr->procID = kControlBevelButtonNormalBevelProc; - } else { - paramsPtr->procID = kControlBevelButtonLargeBevelProc; - } - paramsPtr->isBevel = 1; - } - break; - case TYPE_RADIO_BUTTON: - if (((butPtr->image == None) && (butPtr->bitmap == None)) - || (butPtr->indicatorOn)) { - paramsPtr->initialValue = 1; - paramsPtr->minValue = 0; - paramsPtr->maxValue = 2; - paramsPtr->procID = kControlRadioButtonProc; - } else { - paramsPtr->initialValue = 0; - paramsPtr->minValue = kControlBehaviorOffsetContents| - kControlBehaviorSticky| - kControlContentPictHandle; - paramsPtr->maxValue = 2; - if (butPtr->borderWidth <= 2) { - paramsPtr->procID = kControlBevelButtonSmallBevelProc; - } else if (butPtr->borderWidth == 3) { - paramsPtr->procID = kControlBevelButtonNormalBevelProc; - } else { - paramsPtr->procID = kControlBevelButtonLargeBevelProc; - } - paramsPtr->isBevel = 1; - } - break; - case TYPE_CHECK_BUTTON: - if (((butPtr->image == None) - && (butPtr->bitmap == None)) - || (butPtr->indicatorOn)) { - paramsPtr->initialValue = 1; - paramsPtr->minValue = 0; - paramsPtr->maxValue = 2; - paramsPtr->procID = kControlCheckBoxProc; - } else { - paramsPtr->initialValue = 0; - paramsPtr->minValue = kControlBehaviorOffsetContents - | kControlBehaviorSticky - | kControlContentPictHandle; - paramsPtr->maxValue = 2; - if (butPtr->borderWidth <= 2) { - paramsPtr->procID = kControlBevelButtonSmallBevelProc; - } else if (butPtr->borderWidth == 3) { - paramsPtr->procID = kControlBevelButtonNormalBevelProc; - } else { - paramsPtr->procID = kControlBevelButtonLargeBevelProc; - } - paramsPtr->isBevel = 1; - } - break; + case TYPE_BUTTON: + if ((butPtr->image == None) && (butPtr->bitmap == None)) { + paramsPtr->initialValue = 1; + paramsPtr->minValue = 0; + paramsPtr->maxValue = 1; + paramsPtr->procID = kControlPushButtonProc; + } else { + paramsPtr->initialValue = 0; + paramsPtr->minValue = kControlBehaviorOffsetContents | + kControlContentPictHandle; + paramsPtr->maxValue = 1; + if (butPtr->borderWidth <= 2) { + paramsPtr->procID = kControlBevelButtonSmallBevelProc; + } else if (butPtr->borderWidth == 3) { + paramsPtr->procID = kControlBevelButtonNormalBevelProc; + } else { + paramsPtr->procID = kControlBevelButtonLargeBevelProc; + } + paramsPtr->isBevel = 1; + } + break; + case TYPE_RADIO_BUTTON: + if (((butPtr->image == None) && (butPtr->bitmap == None)) + || (butPtr->indicatorOn)) { + paramsPtr->initialValue = 1; + paramsPtr->minValue = 0; + paramsPtr->maxValue = 2; + paramsPtr->procID = kControlRadioButtonProc; + } else { + paramsPtr->initialValue = 0; + paramsPtr->minValue = kControlBehaviorOffsetContents | + kControlBehaviorSticky | kControlContentPictHandle; + paramsPtr->maxValue = 2; + if (butPtr->borderWidth <= 2) { + paramsPtr->procID = kControlBevelButtonSmallBevelProc; + } else if (butPtr->borderWidth == 3) { + paramsPtr->procID = kControlBevelButtonNormalBevelProc; + } else { + paramsPtr->procID = kControlBevelButtonLargeBevelProc; + } + paramsPtr->isBevel = 1; + } + break; + case TYPE_CHECK_BUTTON: + if (((butPtr->image == None) && (butPtr->bitmap == None)) + || (butPtr->indicatorOn)) { + paramsPtr->initialValue = 1; + paramsPtr->minValue = 0; + paramsPtr->maxValue = 2; + paramsPtr->procID = kControlCheckBoxProc; + } else { + paramsPtr->initialValue = 0; + paramsPtr->minValue = kControlBehaviorOffsetContents | + kControlBehaviorSticky | kControlContentPictHandle; + paramsPtr->maxValue = 2; + if (butPtr->borderWidth <= 2) { + paramsPtr->procID = kControlBevelButtonSmallBevelProc; + } else if (butPtr->borderWidth == 3) { + paramsPtr->procID = kControlBevelButtonNormalBevelProc; + } else { + paramsPtr->procID = kControlBevelButtonLargeBevelProc; + } + paramsPtr->isBevel = 1; + } + break; } -} +} + /* *---------------------------------------------------------------------- * * TkMacOSXComputeDrawParams -- * - * This procedure computes the various parameters used - * when drawing a button - * These are determined by the various tk button parameters + * This procedure computes the various parameters used + * when drawing a button + * These are determined by the various tk button parameters * * Results: - * 1 if control will be used, 0 otherwise. + * 1 if control will be used, 0 otherwise. * * Side effects: - * Sets the button draw parameters + * Sets the button draw parameters * *---------------------------------------------------------------------- */ static int -TkMacOSXComputeDrawParams(TkButton * butPtr, DrawParams * dpPtr) +TkMacOSXComputeDrawParams( + TkButton *butPtr, + DrawParams *dpPtr) { - dpPtr->hasImageOrBitmap = ((butPtr->image != NULL) - || (butPtr->bitmap != None)); - dpPtr->offset = (butPtr->type == TYPE_BUTTON) - && dpPtr->hasImageOrBitmap; + dpPtr->hasImageOrBitmap = ((butPtr->image != NULL) + || (butPtr->bitmap != None)); + dpPtr->offset = (butPtr->type == TYPE_BUTTON) + && dpPtr->hasImageOrBitmap; dpPtr->border = butPtr->normalBorder; - if ((butPtr->state == STATE_DISABLED) - && (butPtr->disabledFg != NULL)) { - dpPtr->gc = butPtr->disabledGC; - } else if ((butPtr->type == TYPE_BUTTON) - && (butPtr->state == STATE_ACTIVE)) { - dpPtr->gc = butPtr->activeTextGC; - dpPtr->border = butPtr->activeBorder; + if ((butPtr->state == STATE_DISABLED) && (butPtr->disabledFg != NULL)) { + dpPtr->gc = butPtr->disabledGC; + } else if (butPtr->type == TYPE_BUTTON && butPtr->state == STATE_ACTIVE) { + dpPtr->gc = butPtr->activeTextGC; + dpPtr->border = butPtr->activeBorder; } else { - dpPtr->gc = butPtr->normalTextGC; + dpPtr->gc = butPtr->normalTextGC; } - if ((butPtr->flags & SELECTED) - && (butPtr->state != STATE_ACTIVE) - && (butPtr->selectBorder != NULL) - && !butPtr->indicatorOn) { - dpPtr->border = butPtr->selectBorder; + if ((butPtr->flags & SELECTED) && (butPtr->state != STATE_ACTIVE) + && (butPtr->selectBorder != NULL) && !butPtr->indicatorOn) { + dpPtr->border = butPtr->selectBorder; } - + /* * Override the relief specified for the button if this is a * checkbutton or radiobutton and there's no indicator. @@ -1581,69 +1522,70 @@ TkMacOSXComputeDrawParams(TkButton * butPtr, DrawParams * dpPtr) dpPtr->relief = butPtr->relief; if ((butPtr->type >= TYPE_CHECK_BUTTON) && !butPtr->indicatorOn) { - if (!dpPtr->hasImageOrBitmap) { - dpPtr->relief = (butPtr->flags & SELECTED) ? TK_RELIEF_SUNKEN - : TK_RELIEF_RAISED; - } + if (!dpPtr->hasImageOrBitmap) { + dpPtr->relief = (butPtr->flags & SELECTED) ? TK_RELIEF_SUNKEN + : TK_RELIEF_RAISED; + } } /* * Determine the draw type */ + if (butPtr->type == TYPE_LABEL) { - dpPtr->drawType = DRAW_LABEL; + dpPtr->drawType = DRAW_LABEL; } else if (butPtr->type == TYPE_BUTTON) { - if (!dpPtr->hasImageOrBitmap) { - dpPtr->drawType = DRAW_CONTROL; - } else if (butPtr->image != None) { - dpPtr->drawType = DRAW_BEVEL; - } else { - /* - * TO DO - The current way the we draw bitmaps (XCopyPlane) - * uses CopyDeepMask in this one case. The Picture recording - * does not record this call, and so we can't use the - * Appearance bevel button here. The only case that would - * exercise this is if you use a bitmap, with - * -data & -mask specified. We should probably draw the - * appearance button and overprint the image in this case. - * This just punts and draws the old-style, ugly, button. - */ - - if (dpPtr->gc->clip_mask == 0) { - dpPtr->drawType = DRAW_BEVEL; - } else { - TkpClipMask *clipPtr = (TkpClipMask*) dpPtr->gc->clip_mask; - if ((clipPtr->type == TKP_CLIP_PIXMAP) && - (clipPtr->value.pixmap != butPtr->bitmap)) { - dpPtr->drawType = DRAW_CUSTOM; - } else { - dpPtr->drawType = DRAW_BEVEL; - } - } - } + if (!dpPtr->hasImageOrBitmap) { + dpPtr->drawType = DRAW_CONTROL; + } else if (butPtr->image != None) { + dpPtr->drawType = DRAW_BEVEL; + } else { + /* + * TO DO - The current way the we draw bitmaps (XCopyPlane) + * uses CopyDeepMask in this one case. The Picture recording + * does not record this call, and so we can't use the + * Appearance bevel button here. The only case that would + * exercise this is if you use a bitmap, with + * -data & -mask specified. We should probably draw the + * appearance button and overprint the image in this case. + * This just punts and draws the old-style, ugly, button. + */ + + if (dpPtr->gc->clip_mask == 0) { + dpPtr->drawType = DRAW_BEVEL; + } else { + TkpClipMask *clipPtr = (TkpClipMask *) dpPtr->gc->clip_mask; + + if ((clipPtr->type == TKP_CLIP_PIXMAP) && + (clipPtr->value.pixmap != butPtr->bitmap)) { + dpPtr->drawType = DRAW_CUSTOM; + } else { + dpPtr->drawType = DRAW_BEVEL; + } + } + } + } else if (butPtr->indicatorOn) { + dpPtr->drawType = DRAW_CONTROL; + } else if (dpPtr->hasImageOrBitmap) { + if (dpPtr->gc->clip_mask == 0) { + dpPtr->drawType = DRAW_BEVEL; + } else { + TkpClipMask *clipPtr = (TkpClipMask*) dpPtr->gc->clip_mask; + + if ((clipPtr->type == TKP_CLIP_PIXMAP) && + (clipPtr->value.pixmap != butPtr->bitmap)) { + dpPtr->drawType = DRAW_CUSTOM; + } else { + dpPtr->drawType = DRAW_BEVEL; + } + } } else { - if (butPtr->indicatorOn) { - dpPtr->drawType = DRAW_CONTROL; - } else if (dpPtr->hasImageOrBitmap) { - if (dpPtr->gc->clip_mask == 0) { - dpPtr->drawType = DRAW_BEVEL; - } else { - TkpClipMask *clipPtr = (TkpClipMask*) dpPtr->gc->clip_mask; - if ((clipPtr->type == TKP_CLIP_PIXMAP) && - (clipPtr->value.pixmap != butPtr->bitmap)) { - dpPtr->drawType = DRAW_CUSTOM; - } else { - dpPtr->drawType = DRAW_BEVEL; - } - } - } else { - dpPtr->drawType = DRAW_CUSTOM; - } + dpPtr->drawType = DRAW_CUSTOM; } if ((dpPtr->drawType == DRAW_CONTROL) || (dpPtr->drawType == DRAW_BEVEL)) { - return 1; + return 1; } else { - return 0; + return 0; } } diff --git a/macosx/tkMacOSXCarbonEvents.c b/macosx/tkMacOSXCarbonEvents.c index 18c519e..a6916bc 100644 --- a/macosx/tkMacOSXCarbonEvents.c +++ b/macosx/tkMacOSXCarbonEvents.c @@ -11,56 +11,56 @@ * application event target. * * Copyright 2001, Apple Computer, Inc. - * Copyright (c) 2005 Daniel A. Steffen + * Copyright (c) 2005-2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * The following terms apply to all files originating from Apple - * Computer, Inc. ("Apple") and associated with the software - * unless explicitly disclaimed in individual files. - * - * - * Apple hereby grants permission to use, copy, modify, - * distribute, and license this software and its documentation - * for any purpose, provided that existing copyright notices are - * retained in all copies and that this notice is included - * verbatim in any distributions. No written agreement, license, - * or royalty fee is required for any of the authorized - * uses. Modifications to this software may be copyrighted by - * their authors and need not follow the licensing terms - * described here, provided that the new terms are clearly - * indicated on the first page of each file where they apply. - * - * - * IN NO EVENT SHALL APPLE, THE AUTHORS OR DISTRIBUTORS OF THE - * SOFTWARE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, - * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF - * THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, - * EVEN IF APPLE OR THE AUTHORS HAVE BEEN ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. APPLE, THE AUTHORS AND - * DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS - * SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND APPLE,THE - * AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE - * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * GOVERNMENT USE: If you are acquiring this software on behalf - * of the U.S. government, the Government shall have only - * "Restricted Rights" in the software and related documentation - * as defined in the Federal Acquisition Regulations (FARs) in - * Clause 52.227.19 (c) (2). If you are acquiring the software - * on behalf of the Department of Defense, the software shall be - * classified as "Commercial Computer Software" and the - * Government shall have only "Restricted Rights" as defined in - * Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the - * foregoing, the authors grant the U.S. Government and others - * acting in its behalf permission to use and distribute the - * software in accordance with the terms specified in this - * license. - * - * RCS: @(#) $Id: tkMacOSXCarbonEvents.c,v 1.15 2007/04/21 19:06:37 hobbs Exp $ + * The following terms apply to all files originating from Apple + * Computer, Inc. ("Apple") and associated with the software + * unless explicitly disclaimed in individual files. + * + * + * Apple hereby grants permission to use, copy, modify, + * distribute, and license this software and its documentation + * for any purpose, provided that existing copyright notices are + * retained in all copies and that this notice is included + * verbatim in any distributions. No written agreement, license, + * or royalty fee is required for any of the authorized + * uses. Modifications to this software may be copyrighted by + * their authors and need not follow the licensing terms + * described here, provided that the new terms are clearly + * indicated on the first page of each file where they apply. + * + * + * IN NO EVENT SHALL APPLE, THE AUTHORS OR DISTRIBUTORS OF THE + * SOFTWARE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF + * THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, + * EVEN IF APPLE OR THE AUTHORS HAVE BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. APPLE, THE AUTHORS AND + * DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS + * SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND APPLE,THE + * AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE + * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * GOVERNMENT USE: If you are acquiring this software on behalf + * of the U.S. government, the Government shall have only + * "Restricted Rights" in the software and related documentation + * as defined in the Federal Acquisition Regulations (FARs) in + * Clause 52.227.19 (c) (2). If you are acquiring the software + * on behalf of the Department of Defense, the software shall be + * classified as "Commercial Computer Software" and the + * Government shall have only "Restricted Rights" as defined in + * Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the + * foregoing, the authors grant the U.S. Government and others + * acting in its behalf permission to use and distribute the + * software in accordance with the terms specified in this + * license. + * + * RCS: @(#) $Id: tkMacOSXCarbonEvents.c,v 1.16 2007/04/23 21:24:33 das Exp $ */ #include "tkMacOSXInt.h" @@ -68,66 +68,79 @@ #include "tkMacOSXDebug.h" /* -#ifdef TK_MAC_DEBUG +#ifdef TK_MAC_DEBUG #define TK_MAC_DEBUG_CARBON_EVENTS #endif */ -/* Declarations of functions used only in this file */ +/* + * Declarations of functions used only in this file: + */ + static OSStatus CarbonEventHandlerProc(EventHandlerCallRef callRef, - EventRef event, void *userData); -static OSStatus InstallStandardApplicationEventHandler(); -static void ExitRaelEventHandlerProc (EventHandlerCallRef, EventRef, void*) - __attribute__ ((__noreturn__)); + EventRef event, void *userData); +static OSStatus InstallStandardApplicationEventHandler(void); +static void ExitRaelEventHandlerProc(EventHandlerCallRef callRef, + EventRef event, void *userData) __attribute__ ((__noreturn__)); static void CarbonTimerProc(EventLoopTimerRef timer, void *userData); -/* Static data used by several functions in this file */ +/* + * Static data used by several functions in this file: + */ + static jmp_buf exitRaelJmpBuf; static EventLoopTimerRef carbonTimer = NULL; static int carbonTimerEnabled = 0; +static EventHandlerUPP carbonEventHandlerUPP = NULL; +static Tcl_Interp *carbonEventInterp = NULL; +static int inTrackingLoop = 0; + /* *---------------------------------------------------------------------- * * CarbonEventHandlerProc -- * - * This procedure is the handler for all registered CarbonEvents. + * This procedure is the handler for all registered CarbonEvents. * * Results: - * OS status code. + * OS status code. * * Side effects: - * Dispatches CarbonEvents. + * Dispatches CarbonEvents. * *---------------------------------------------------------------------- */ static OSStatus -CarbonEventHandlerProc ( - EventHandlerCallRef callRef, - EventRef event, - void *userData) +CarbonEventHandlerProc( + EventHandlerCallRef callRef, + EventRef event, + void *userData) { - OSStatus result = eventNotHandledErr; - TkMacOSXEvent macEvent; - MacEventStatus eventStatus; + OSStatus err = eventNotHandledErr; + TkMacOSXEvent macEvent; + MacEventStatus eventStatus; macEvent.eventRef = event; - macEvent.eClass = GetEventClass(macEvent.eventRef); - macEvent.eKind = GetEventKind(macEvent.eventRef); + macEvent.eClass = GetEventClass(event); + macEvent.eKind = GetEventKind(event); macEvent.interp = (Tcl_Interp *) userData; + macEvent.callRef = callRef; bzero(&eventStatus, sizeof(eventStatus)); -#if defined(TK_MAC_DEBUG) && defined(TK_MAC_DEBUG_CARBON_EVENTS) - char buf [256]; +#ifdef TK_MAC_DEBUG_CARBON_EVENTS if (macEvent.eKind != kEventMouseMoved && macEvent.eKind != kEventMouseDragged) { - TkMacOSXCarbonEventToAscii(event, buf); - fprintf(stderr, "CarbonEventHandlerProc started handling %s\n", buf); + TkMacOSXDbgMsg("Started handling %s", + TkMacOSXCarbonEventToAscii(event)); TkMacOSXInitNamedDebugSymbol(HIToolbox, void, _DebugPrintEvent, EventRef inEvent); if (_DebugPrintEvent) { - /* Carbon-internal event debugging (c.f. Technote 2124) */ + /* + * Carbon-internal event debugging (c.f. Technote 2124) + */ + _DebugPrintEvent(event); } } @@ -135,18 +148,18 @@ CarbonEventHandlerProc ( TkMacOSXProcessEvent(&macEvent,&eventStatus); if (eventStatus.stopProcessing) { - result = noErr; + err = noErr; } -#if defined(TK_MAC_DEBUG) && defined(TK_MAC_DEBUG_CARBON_EVENTS) +#ifdef TK_MAC_DEBUG_CARBON_EVENTS if (macEvent.eKind != kEventMouseMoved && macEvent.eKind != kEventMouseDragged) { - fprintf(stderr, - "CarbonEventHandlerProc finished handling %s: %s handled\n", - buf, eventStatus.stopProcessing ? " " : "not"); + TkMacOSXDbgMsg("Finished handling %s: %s handled", + TkMacOSXCarbonEventToAscii(event), + eventStatus.stopProcessing ? " " : "not"); } #endif /* TK_MAC_DEBUG_CARBON_EVENTS */ - return result; + return err; } /* @@ -154,104 +167,95 @@ CarbonEventHandlerProc ( * * TkMacOSXInitCarbonEvents -- * - * This procedure initializes all CarbonEvent handlers. + * This procedure initializes all CarbonEvent handlers. * * Results: - * None. + * None. * * Side effects: - * Handlers for Carbon Events are registered. + * Handlers for Carbon Events are registered. * *---------------------------------------------------------------------- */ MODULE_SCOPE void -TkMacOSXInitCarbonEvents ( - Tcl_Interp *interp) +TkMacOSXInitCarbonEvents( + Tcl_Interp *interp) { - OSStatus err; const EventTypeSpec dispatcherEventTypes[] = { - {kEventClassMouse, kEventMouseDown}, - {kEventClassMouse, kEventMouseUp}, - {kEventClassMouse, kEventMouseMoved}, - {kEventClassMouse, kEventMouseDragged}, - {kEventClassMouse, kEventMouseWheelMoved}, - {kEventClassWindow, kEventWindowUpdate}, - {kEventClassWindow, kEventWindowActivated}, - {kEventClassWindow, kEventWindowDeactivated}, - {kEventClassKeyboard, kEventRawKeyDown}, - {kEventClassKeyboard, kEventRawKeyRepeat}, - {kEventClassKeyboard, kEventRawKeyUp}, - {kEventClassKeyboard, kEventRawKeyModifiersChanged}, - {kEventClassKeyboard, kEventRawKeyRepeat}, - {kEventClassApplication, kEventAppActivated}, - {kEventClassApplication, kEventAppDeactivated}, - {kEventClassApplication, kEventAppQuit}, + {kEventClassKeyboard, kEventRawKeyDown}, + {kEventClassKeyboard, kEventRawKeyRepeat}, + {kEventClassKeyboard, kEventRawKeyUp}, + {kEventClassKeyboard, kEventRawKeyModifiersChanged}, + {kEventClassKeyboard, kEventRawKeyRepeat}, }; const EventTypeSpec applicationEventTypes[] = { - {kEventClassMenu, kEventMenuBeginTracking}, - {kEventClassMenu, kEventMenuEndTracking}, - {kEventClassCommand, kEventCommandProcess}, - {kEventClassCommand, kEventCommandUpdateStatus}, - {kEventClassMouse, kEventMouseWheelMoved}, - {kEventClassWindow, kEventWindowExpanded}, - {kEventClassApplication, kEventAppHidden}, - {kEventClassApplication, kEventAppShown}, - {kEventClassApplication, kEventAppAvailableWindowBoundsChanged}, + {kEventClassMenu, kEventMenuBeginTracking}, + {kEventClassMenu, kEventMenuEndTracking}, + {kEventClassMenu, kEventMenuOpening}, + {kEventClassMenu, kEventMenuTargetItem}, + {kEventClassCommand, kEventCommandProcess}, + {kEventClassCommand, kEventCommandUpdateStatus}, + {kEventClassApplication, kEventAppActivated}, + {kEventClassApplication, kEventAppDeactivated}, + {kEventClassApplication, kEventAppQuit}, + {kEventClassApplication, kEventAppHidden}, + {kEventClassApplication, kEventAppShown}, + {kEventClassApplication, kEventAppAvailableWindowBoundsChanged}, + {kEventClassAppearance, kEventAppearanceScrollBarVariantChanged}, }; - EventHandlerUPP handler = NewEventHandlerUPP(CarbonEventHandlerProc); - err = InstallStandardApplicationEventHandler(); - if (err != noErr) { -#ifdef TK_MAC_DEBUG - fprintf(stderr, "InstallStandardApplicationEventHandler failed, %d\n", - (int) err); -#endif - } - err = InstallEventHandler(GetEventDispatcherTarget(), handler, - GetEventTypeCount(dispatcherEventTypes), dispatcherEventTypes, - (void *) interp, NULL); - if (err != noErr) { -#ifdef TK_MAC_DEBUG - fprintf(stderr, "InstallEventHandler failed, %d\n", (int) err); -#endif - } - err = InstallEventHandler(GetApplicationEventTarget(), handler, - GetEventTypeCount(applicationEventTypes), applicationEventTypes, - (void *) interp, NULL); - if (err != noErr) { -#ifdef TK_MAC_DEBUG - fprintf(stderr, "InstallEventHandler failed, %d\n", (int) err); -#endif - } + carbonEventHandlerUPP = NewEventHandlerUPP(CarbonEventHandlerProc); + carbonEventInterp = interp; + ChkErr(InstallStandardApplicationEventHandler); + ChkErr(InstallEventHandler, GetEventDispatcherTarget(), + carbonEventHandlerUPP, GetEventTypeCount(dispatcherEventTypes), + dispatcherEventTypes, (void *) carbonEventInterp, NULL); + ChkErr(InstallEventHandler, GetApplicationEventTarget(), + carbonEventHandlerUPP, GetEventTypeCount(applicationEventTypes), + applicationEventTypes, (void *) carbonEventInterp, NULL); -#if defined(TK_MAC_DEBUG) && defined(TK_MAC_DEBUG_CARBON_EVENTS) - TkMacOSXInitNamedDebugSymbol(HIToolbox, void, TraceEventByName, char*); - if (TraceEventByName) { +#ifdef TK_MAC_DEBUG_CARBON_EVENTS + TkMacOSXInitNamedDebugSymbol(HIToolbox, void, _TraceEventByName, + CFStringRef); + if (_TraceEventByName) { /* Carbon-internal event debugging (c.f. Technote 2124) */ - TraceEventByName("kEventMouseDown"); - TraceEventByName("kEventMouseUp"); - TraceEventByName("kEventMouseWheelMoved"); - TraceEventByName("kEventMouseScroll"); - TraceEventByName("kEventWindowUpdate"); - TraceEventByName("kEventWindowActivated"); - TraceEventByName("kEventWindowDeactivated"); - TraceEventByName("kEventRawKeyDown"); - TraceEventByName("kEventRawKeyRepeat"); - TraceEventByName("kEventRawKeyUp"); - TraceEventByName("kEventRawKeyModifiersChanged"); - TraceEventByName("kEventRawKeyRepeat"); - TraceEventByName("kEventAppActivated"); - TraceEventByName("kEventAppDeactivated"); - TraceEventByName("kEventAppQuit"); - TraceEventByName("kEventMenuBeginTracking"); - TraceEventByName("kEventMenuEndTracking"); - TraceEventByName("kEventCommandProcess"); - TraceEventByName("kEventCommandUpdateStatus"); - TraceEventByName("kEventWindowExpanded"); - TraceEventByName("kEventAppHidden"); - TraceEventByName("kEventAppShown"); - TraceEventByName("kEventAppAvailableWindowBoundsChanged"); + _TraceEventByName(CFSTR("kEventRawKeyDown")); + _TraceEventByName(CFSTR("kEventRawKeyRepeat")); + _TraceEventByName(CFSTR("kEventRawKeyUp")); + _TraceEventByName(CFSTR("kEventRawKeyModifiersChanged")); + _TraceEventByName(CFSTR("kEventRawKeyRepeat")); + _TraceEventByName(CFSTR("kEventMenuBeginTracking")); + _TraceEventByName(CFSTR("kEventMenuEndTracking")); + _TraceEventByName(CFSTR("kEventMenuOpening")); + _TraceEventByName(CFSTR("kEventMenuTargetItem")); + _TraceEventByName(CFSTR("kEventCommandProcess")); + _TraceEventByName(CFSTR("kEventCommandUpdateStatus")); + _TraceEventByName(CFSTR("kEventAppActivated")); + _TraceEventByName(CFSTR("kEventAppDeactivated")); + _TraceEventByName(CFSTR("kEventAppQuit")); + _TraceEventByName(CFSTR("kEventAppHidden")); + _TraceEventByName(CFSTR("kEventAppShown")); + _TraceEventByName(CFSTR("kEventAppAvailableWindowBoundsChanged")); + _TraceEventByName(CFSTR("kEventAppearanceScrollBarVariantChanged")); + _TraceEventByName(CFSTR("kEventMouseDown")); + _TraceEventByName(CFSTR("kEventMouseUp")); +#if 0 + _TraceEventByName(CFSTR("kEventMouseMoved")); + _TraceEventByName(CFSTR("kEventMouseDragged")); +#endif + _TraceEventByName(CFSTR("kEventMouseWheelMoved")); + _TraceEventByName(CFSTR("kEventMouseScroll")); + _TraceEventByName(CFSTR("kEventWindowActivated")); + _TraceEventByName(CFSTR("kEventWindowDeactivated")); + _TraceEventByName(CFSTR("kEventWindowUpdate")); + _TraceEventByName(CFSTR("kEventWindowExpanded")); + _TraceEventByName(CFSTR("kEventWindowBoundsChanged")); + _TraceEventByName(CFSTR("kEventWindowDragStarted")); + _TraceEventByName(CFSTR("kEventWindowDragCompleted")); + _TraceEventByName(CFSTR("kEventWindowConstrain")); + _TraceEventByName(CFSTR("kEventWindowGetRegion")); + _TraceEventByName(CFSTR("kEventWindowDrawContent")); } #endif /* TK_MAC_DEBUG_CARBON_EVENTS */ } @@ -259,22 +263,66 @@ TkMacOSXInitCarbonEvents ( /* *---------------------------------------------------------------------- * + * TkMacOSXInstallWindowCarbonEventHandler -- + * + * This procedure installs our window CarbonEvent handler. + * + * Results: + * None. + * + * Side effects: + * Handler for Carbon Events is registered. + * + *---------------------------------------------------------------------- + */ + +MODULE_SCOPE void +TkMacOSXInstallWindowCarbonEventHandler( + Tcl_Interp *interp, WindowRef window) +{ + const EventTypeSpec windowEventTypes[] = { + {kEventClassMouse, kEventMouseDown}, + {kEventClassMouse, kEventMouseUp}, + {kEventClassMouse, kEventMouseMoved}, + {kEventClassMouse, kEventMouseDragged}, + {kEventClassMouse, kEventMouseWheelMoved}, + {kEventClassWindow, kEventWindowActivated}, + {kEventClassWindow, kEventWindowDeactivated}, + {kEventClassWindow, kEventWindowUpdate}, + {kEventClassWindow, kEventWindowExpanded}, + {kEventClassWindow, kEventWindowBoundsChanged}, + {kEventClassWindow, kEventWindowDragStarted}, + {kEventClassWindow, kEventWindowDragCompleted}, + {kEventClassWindow, kEventWindowConstrain}, + {kEventClassWindow, kEventWindowGetRegion}, + {kEventClassWindow, kEventWindowDrawContent}, + }; + + ChkErr(InstallEventHandler, GetWindowEventTarget(window), + carbonEventHandlerUPP, GetEventTypeCount(windowEventTypes), + windowEventTypes, (void *) (interp ? interp : carbonEventInterp), + NULL); +} + +/* + *---------------------------------------------------------------------- + * * InstallStandardApplicationEventHandler -- * - * This procedure installs the carbon standard application event - * handler. + * This procedure installs the carbon standard application event + * handler. * * Results: - * OS status code. + * OS status code. * * Side effects: - * Standard handlers for application Carbon Events are registered. + * Standard handlers for application Carbon Events are registered. * *---------------------------------------------------------------------- */ static OSStatus -InstallStandardApplicationEventHandler() +InstallStandardApplicationEventHandler(void) { /* * This is a hack to workaround missing Carbon API to install the standard @@ -286,9 +334,12 @@ InstallStandardApplicationEventHandler() * called first off from RAEL by posting a high priority dummy event. * This workaround is derived from a similar approach in Technical Q&A 1061. */ - enum { kExitRaelEvent = 'ExiT' }; - const EventTypeSpec exitRaelEventType = - { kExitRaelEvent, kExitRaelEvent}; + enum { + kExitRaelEvent = 'ExiT' + }; + const EventTypeSpec exitRaelEventType = { + kExitRaelEvent, kExitRaelEvent + }; EventHandlerUPP exitRaelEventHandler; EventHandlerRef exitRaelEventHandlerRef = NULL; EventRef exitRaelEvent = NULL; @@ -297,22 +348,26 @@ InstallStandardApplicationEventHandler() exitRaelEventHandler = NewEventHandlerUPP( (EventHandlerProcPtr) ExitRaelEventHandlerProc); if (exitRaelEventHandler) { - err = InstallEventHandler(GetEventDispatcherTarget(), + err = ChkErr(InstallEventHandler, GetEventDispatcherTarget(), exitRaelEventHandler, 1, &exitRaelEventType, NULL, &exitRaelEventHandlerRef); } if (err == noErr) { - err = CreateEvent(NULL, kExitRaelEvent, kExitRaelEvent, + err = ChkErr(CreateEvent, NULL, kExitRaelEvent, kExitRaelEvent, GetCurrentEventTime(), kEventAttributeNone, &exitRaelEvent); } if (err == noErr) { - err = PostEventToQueue(GetMainEventQueue(), exitRaelEvent, + err = ChkErr(PostEventToQueue, GetMainEventQueue(), exitRaelEvent, kEventPriorityHigh); } if (err == noErr) { if (!setjmp(exitRaelJmpBuf)) { RunApplicationEventLoop(); - /* This point should never be reached ! */ + + /* + * This point should never be reached! + */ + Tcl_Panic("RunApplicationEventLoop exited !"); } } @@ -333,23 +388,24 @@ InstallStandardApplicationEventHandler() * * ExitRaelEventHandlerProc -- * - * This procedure is the dummy event handler used to break out of - * RAEL via longjmp, it is called as the first ever event handler - * in RAEL by posting a high priority dummy event. + * This procedure is the dummy event handler used to break out of + * RAEL via longjmp, it is called as the first ever event handler + * in RAEL by posting a high priority dummy event. * * Results: - * None. Never returns ! + * None. Never returns ! * * Side effects: - * longjmp back to InstallStandardApplicationEventHandler(). + * longjmp back to InstallStandardApplicationEventHandler(). * *---------------------------------------------------------------------- */ static void -ExitRaelEventHandlerProc ( - EventHandlerCallRef callRef, - EventRef event, void *userData) +ExitRaelEventHandlerProc( + EventHandlerCallRef callRef, + EventRef event, + void *userData) { longjmp(exitRaelJmpBuf, 1); } @@ -357,37 +413,57 @@ ExitRaelEventHandlerProc ( /* *---------------------------------------------------------------------- * + * TkMacOSXRunTclEventLoop -- + * + * Process a limited number of tcl events. + * + * Results: + * Returns 1 if events were handled and 0 otherwise. + * + * Side effects: + * Runs the Tcl event loop. + * + *---------------------------------------------------------------------- + */ + +MODULE_SCOPE int +TkMacOSXRunTclEventLoop(void) +{ + int i = 4, result = 0; + + /* Avoid starving main event loop: process at most 4 events. */ + while(--i && Tcl_ServiceAll()) { + result = 1; + } + return result; +} + +/* + *---------------------------------------------------------------------- + * * CarbonTimerProc -- * - * This procedure is the carbon timer handler that runs the tcl - * event loop periodically. It does not process TCL_WINDOW_EVENTS - * to avoid reentry issues with Carbon, nor TCL_IDLE_EVENTS since - * it is only intended to be called during short periods of busy - * time such as during menu tracking. + * This procedure is the carbon timer handler that runs the tcl + * event loop periodically. * * Results: - * None. + * None. * * Side effects: - * Runs the Tcl event loop. + * Runs the Tcl event loop. * *---------------------------------------------------------------------- */ static void -CarbonTimerProc ( - EventLoopTimerRef timer, - void *userData) +CarbonTimerProc( + EventLoopTimerRef timer, + void *userData) { - if(carbonTimerEnabled) { - /* Avoid starving main event loop: process at most 4 events. */ - int i = 4; - while(--i && Tcl_DoOneEvent( - TCL_FILE_EVENTS|TCL_TIMER_EVENTS|TCL_DONT_WAIT)) { -#if defined(TK_MAC_DEBUG) && defined(TK_MAC_DEBUG_CARBON_EVENTS) - fprintf(stderr, "Processed tcl event from carbon timer\n"); + if(carbonTimerEnabled > 0 && TkMacOSXRunTclEventLoop()) { +#ifdef TK_MAC_DEBUG_CARBON_EVENTS + TkMacOSXDbgMsg("Processed tcl events from carbon timer"); #endif /* TK_MAC_DEBUG_CARBON_EVENTS */ - } } } @@ -396,80 +472,183 @@ CarbonTimerProc ( * * TkMacOSXStartTclEventLoopCarbonTimer -- * - * This procedure installs (if necessary) and starts a carbon - * event timer that runs the tcl event loop periodically. - * It should be called whenever a nested carbon event loop is - * run by HIToolbox (e.g. during menutracking) to ensure that - * non-window non-idle tcl events are processed. + * This procedure installs (if necessary) and starts a carbon + * event timer that runs the tcl event loop periodically. + * It should be called whenever a nested carbon event loop might + * run by HIToolbox (e.g. during mouse tracking) to ensure that + * tcl events continue to be processed. * * Results: - * OS status code. + * OS status code. * * Side effects: - * Carbon event timer is installed and started. + * Carbon event timer is installed and started. * *---------------------------------------------------------------------- */ MODULE_SCOPE OSStatus -TkMacOSXStartTclEventLoopCarbonTimer() +TkMacOSXStartTclEventLoopCarbonTimer(void) { - OSStatus err; + OSStatus err = noErr; - if(!carbonTimer) { - EventLoopTimerUPP timerUPP = NewEventLoopTimerUPP(CarbonTimerProc); - err = InstallEventLoopTimer(GetMainEventLoop(), kEventDurationNoWait, - 5 * kEventDurationMillisecond, timerUPP, NULL, &carbonTimer); - if (err != noErr) { -#ifdef TK_MAC_DEBUG - fprintf(stderr, "InstallEventLoopTimer failed, %d\n", (int) err); -#endif - } - } else { - err = SetEventLoopTimerNextFireTime(carbonTimer, kEventDurationNoWait); - if (err != noErr) { -#ifdef TK_MAC_DEBUG - fprintf(stderr, "SetEventLoopTimerNextFireTime failed, %d\n", - (int) err); -#endif + if (++carbonTimerEnabled > 0) { + if(!carbonTimer) { + EventLoopTimerUPP timerUPP = NewEventLoopTimerUPP(CarbonTimerProc); + + err = ChkErr(InstallEventLoopTimer, GetMainEventLoop(), + 5 * kEventDurationMillisecond, + 5 * kEventDurationMillisecond, + timerUPP, NULL, &carbonTimer); + } else { + err = ChkErr(SetEventLoopTimerNextFireTime, carbonTimer, + 5 * kEventDurationMillisecond); } } - carbonTimerEnabled = 1; return err; } - + /* *---------------------------------------------------------------------- * * TkMacOSXStopTclEventLoopCarbonTimer -- * - * This procedure stops the carbon event timer started by - * TkMacOSXStartTclEventLoopCarbonTimer(). + * This procedure stops the carbon event timer started by + * TkMacOSXStartTclEventLoopCarbonTimer(). * * Results: - * OS status code. + * OS status code. * * Side effects: - * Carbon event timer is stopped. + * Carbon event timer is stopped. * *---------------------------------------------------------------------- */ MODULE_SCOPE OSStatus -TkMacOSXStopTclEventLoopCarbonTimer() +TkMacOSXStopTclEventLoopCarbonTimer(void) { OSStatus err = noErr; - if(carbonTimer) { - err = SetEventLoopTimerNextFireTime(carbonTimer, kEventDurationForever); - if (err != noErr) { -#ifdef TK_MAC_DEBUG - fprintf(stderr, "SetEventLoopTimerNextFireTime failed, %d\n", - (int) err); -#endif + if (--carbonTimerEnabled == 0) { + if(carbonTimer) { + err = ChkErr(SetEventLoopTimerNextFireTime, carbonTimer, + kEventDurationForever); } } - carbonTimerEnabled = 0; return err; } +/* + *---------------------------------------------------------------------- + * + * TkMacOSXTrackingLoop -- + * + * Call with 1 before entering a mouse tracking loop (e.g. window + * resizing or menu tracking) to enable tcl event processing but + * disable carbon event processing (except for update events) + * during the loop, and with 0 after exiting the loop to reset. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +MODULE_SCOPE void +TkMacOSXTrackingLoop(int tracking) +{ + static int previousServiceMode = TCL_SERVICE_NONE; + + if (tracking) { + inTrackingLoop++; + previousServiceMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); + TkMacOSXStartTclEventLoopCarbonTimer(); +#ifdef TK_MAC_DEBUG_CARBON_EVENTS + TkMacOSXDbgMsg("Entering tracking loop"); +#endif /* TK_MAC_DEBUG_CARBON_EVENTS */ + } else { + TkMacOSXStopTclEventLoopCarbonTimer(); + previousServiceMode = Tcl_SetServiceMode(previousServiceMode); + inTrackingLoop--; +#ifdef TK_MAC_DEBUG_CARBON_EVENTS + TkMacOSXDbgMsg("Exiting tracking loop"); +#endif /* TK_MAC_DEBUG_CARBON_EVENTS */ + } +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXReceiveAndDispatchEvent -- + * + * This receives a carbon event and sends it to the carbon event + * dispatcher. + * + * Results: + * Mac OS status + * + * Side effects: + * This receives and dispatches the next Carbon event. + * + *---------------------------------------------------------------------- + */ +MODULE_SCOPE OSStatus +TkMacOSXReceiveAndDispatchEvent(void) +{ + static EventTargetRef targetRef = NULL; + int numEventTypes = 0; + const EventTypeSpec *eventTypes = NULL; + EventRef eventRef; + OSStatus err; + const EventTypeSpec trackingEventTypes[] = { + {'dniw', kEventWindowUpdate}, + {kEventClassWindow, kEventWindowUpdate}, + }; + + if (inTrackingLoop > 0) { + eventTypes = trackingEventTypes; + numEventTypes = GetEventTypeCount(trackingEventTypes); + } + + /* + * This is a poll, since we have already counted the events coming + * into this routine, and are guaranteed to have one waiting. + */ + + err = ReceiveNextEvent(numEventTypes, eventTypes, + kEventDurationNoWait, true, &eventRef); + if (err == noErr) { +#ifdef TK_MAC_DEBUG_CARBON_EVENTS + UInt32 kind = GetEventKind(eventRef); + + if (kind != kEventMouseMoved && kind != kEventMouseDragged) { + TkMacOSXDbgMsg("Dispatching %s", TkMacOSXCarbonEventToAscii(eventRef)); + TkMacOSXInitNamedDebugSymbol(HIToolbox, void, _DebugPrintEvent, + EventRef inEvent); + if (_DebugPrintEvent) { + /* Carbon-internal event debugging (c.f. Technote 2124) */ + _DebugPrintEvent(eventRef); + } + } +#endif /* TK_MAC_DEBUG_CARBON_EVENTS */ + if (!targetRef) { + targetRef = GetEventDispatcherTarget(); + } + TkMacOSXStartTclEventLoopCarbonTimer(); + err = SendEventToEventTarget(eventRef, targetRef); + TkMacOSXStopTclEventLoopCarbonTimer(); + if (err != noErr && err != eventLoopTimedOutErr + && err != eventNotHandledErr) { + TkMacOSXDbgMsg("SendEventToEventTarget(%s) failed: %ld", + TkMacOSXCarbonEventToAscii(eventRef), err); + } + ReleaseEvent(eventRef); + } else if (err != eventLoopTimedOutErr) { + TkMacOSXDbgMsg("ReceiveNextEvent failed: %ld", err); + } + return err; +} diff --git a/macosx/tkMacOSXClipboard.c b/macosx/tkMacOSXClipboard.c index fb83d02..635d51b 100644 --- a/macosx/tkMacOSXClipboard.c +++ b/macosx/tkMacOSXClipboard.c @@ -1,15 +1,16 @@ /* * tkMacOSXClipboard.c -- * - * This file manages the clipboard for the Tk toolkit. + * This file manages the clipboard for the Tk toolkit. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2006-2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXClipboard.c,v 1.9 2007/04/21 19:06:37 hobbs Exp $ + * RCS: @(#) $Id: tkMacOSXClipboard.c,v 1.10 2007/04/23 21:24:33 das Exp $ */ #include "tkMacOSXInt.h" @@ -21,66 +22,66 @@ * * TkSelGetSelection -- * - * Retrieve the specified selection from another process. For - * now, only fetching XA_STRING from CLIPBOARD is supported. - * Eventually other types should be allowed. - * + * Retrieve the specified selection from another process. For + * now, only fetching XA_STRING from CLIPBOARD is supported. + * Eventually other types should be allowed. + * * Results: - * The return value is a standard Tcl return value. - * If an error occurs (such as no selection exists) - * then an error message is left in the interp's result. + * The return value is a standard Tcl return value. + * If an error occurs (such as no selection exists) + * then an error message is left in the interp's result. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ int TkSelGetSelection( - Tcl_Interp *interp, /* Interpreter to use for reporting - * errors. */ - Tk_Window tkwin, /* Window on whose behalf to retrieve - * the selection (determines display - * from which to retrieve). */ - Atom selection, /* Selection to retrieve. */ - Atom target, /* Desired form in which selection - * is to be returned. */ - Tk_GetSelProc *proc, /* Procedure to call to process the - * selection, once it has been retrieved. */ - ClientData clientData) /* Arbitrary value to pass to proc. */ + Tcl_Interp *interp, /* Interpreter to use for reporting errors. */ + Tk_Window tkwin, /* Window on whose behalf to retrieve the + * selection (determines display from which to + * retrieve). */ + Atom selection, /* Selection to retrieve. */ + Atom target, /* Desired form in which selection is to be + * returned. */ + Tk_GetSelProc *proc, /* Procedure to call to process the selection, + * once it has been retrieved. */ + ClientData clientData) /* Arbitrary value to pass to proc. */ { int result; - int err; + OSStatus err; long length; ScrapRef scrapRef; - char * buf; + char *buf; if ((selection == Tk_InternAtom(tkwin, "CLIPBOARD")) - && (target == XA_STRING)) { - /* - * Get the scrap from the Macintosh global clipboard. - */ - - err = GetCurrentScrap(&scrapRef); - if (err != noErr) { - Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection), - " GetCurrentScrap failed.", (char *) NULL); - return TCL_ERROR; - } + && (target == XA_STRING)) { + /* + * Get the scrap from the Macintosh global clipboard. + */ + + err = ChkErr(GetCurrentScrap, &scrapRef); + if (err != noErr) { + Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection), + " GetCurrentScrap failed.", NULL); + return TCL_ERROR; + } /* * Try UNICODE first */ - err = GetScrapFlavorSize(scrapRef, kScrapFlavorTypeUnicode, &length); - if (err == noErr && length > 0) { + err = ChkErr(GetScrapFlavorSize, scrapRef, kScrapFlavorTypeUnicode, + &length); + if (err == noErr && length > 0) { Tcl_DString ds; char *data; buf = (char *) ckalloc(length + 2); buf[length] = 0; buf[length+1] = 0; /* 2-byte unicode null */ - err = GetScrapFlavorData(scrapRef, kScrapFlavorTypeUnicode, + err = ChkErr(GetScrapFlavorData, scrapRef, kScrapFlavorTypeUnicode, &length, buf); if (err == noErr) { Tcl_DStringInit(&ds); @@ -98,49 +99,49 @@ TkSelGetSelection( } } - err = GetScrapFlavorSize(scrapRef, 'TEXT', &length); - if (err != noErr) { - Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection), - " GetScrapFlavorSize failed.", (char *) NULL); - return TCL_ERROR; - } - if (length > 0) { - Tcl_DString encodedText; - char *data; - - buf = (char *) ckalloc(length + 1); + err = ChkErr(GetScrapFlavorSize, scrapRef, 'TEXT', &length); + if (err != noErr) { + Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection), + " GetScrapFlavorSize failed.", NULL); + return TCL_ERROR; + } + if (length > 0) { + Tcl_DString encodedText; + char *data; + + buf = (char *) ckalloc(length + 1); buf[length] = 0; - err = GetScrapFlavorData(scrapRef, 'TEXT', &length, buf); - if (err != noErr) { - Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection), - " GetScrapFlavorData failed.", (char *) NULL); - return TCL_ERROR; - } - - /* - * Tcl expects '\n' not '\r' as the line break character. - */ - - for (data = buf; *data != '\0'; data++) { - if (*data == '\r') { - *data = '\n'; - } - } - - Tcl_ExternalToUtfDString(TkMacOSXCarbonEncoding, buf, length, - &encodedText); - result = (*proc)(clientData, interp, - Tcl_DStringValue(&encodedText)); - Tcl_DStringFree(&encodedText); - - ckfree(buf); - return result; - } + err = ChkErr(GetScrapFlavorData, scrapRef, 'TEXT', &length, buf); + if (err != noErr) { + Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection), + " GetScrapFlavorData failed.", NULL); + return TCL_ERROR; + } + + /* + * Tcl expects '\n' not '\r' as the line break character. + */ + + for (data = buf; *data != '\0'; data++) { + if (*data == '\r') { + *data = '\n'; + } + } + + Tcl_ExternalToUtfDString(TkMacOSXCarbonEncoding, buf, length, + &encodedText); + result = (*proc)(clientData, interp, + Tcl_DStringValue(&encodedText)); + Tcl_DStringFree(&encodedText); + + ckfree(buf); + return result; + } } - + Tcl_AppendResult(interp, Tk_GetAtomName(tkwin, selection), - " selection doesn't exist or form \"", Tk_GetAtomName(tkwin, target), - "\" not defined", (char *) NULL); + " selection doesn't exist or form \"", + Tk_GetAtomName(tkwin, target), "\" not defined", NULL); return TCL_ERROR; } @@ -149,25 +150,25 @@ TkSelGetSelection( * * TkSetSelectionOwner -- * - * This function claims ownership of the specified selection. - * If the selection is CLIPBOARD, then we empty the system - * clipboard. + * This function claims ownership of the specified selection. + * If the selection is CLIPBOARD, then we empty the system + * clipboard. * * Results: - * None. + * None. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ void XSetSelectionOwner( - Display* display, /* X Display. */ - Atom selection, /* What selection to own. */ - Window owner, /* Window to be the owner. */ - Time time) /* The current time? */ + Display *display, /* X Display. */ + Atom selection, /* What selection to own. */ + Window owner, /* Window to be the owner. */ + Time time) /* The current time? */ { Tk_Window tkwin; TkDisplay *dispPtr; @@ -180,17 +181,16 @@ XSetSelectionOwner( tkwin = (Tk_Window) TkGetMainInfoList()->winPtr; if (selection == Tk_InternAtom(tkwin, "CLIPBOARD")) { + /* + * Only claim and empty the clipboard if we aren't already the + * owner of the clipboard. + */ - /* - * Only claim and empty the clipboard if we aren't already the - * owner of the clipboard. - */ - - dispPtr = TkGetMainInfoList()->winPtr->dispPtr; - if (dispPtr->clipboardActive) { - return; - } - ClearCurrentScrap(); + dispPtr = TkGetMainInfoList()->winPtr->dispPtr; + if (dispPtr->clipboardActive) { + return; + } + ClearCurrentScrap(); } } @@ -199,23 +199,24 @@ XSetSelectionOwner( * * TkSelUpdateClipboard -- * - * This function is called to force the clipboard to be updated - * after new data is added. On the Mac we don't need to do - * anything. + * This function is called to force the clipboard to be updated + * after new data is added. On the Mac we don't need to do + * anything. * * Results: - * None. + * None. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ void TkSelUpdateClipboard( - TkWindow *winPtr, /* Window associated with clipboard. */ - TkClipboardTarget *targetPtr) /* Info about the content. */ + TkWindow *winPtr, /* Window associated with clipboard. */ + TkClipboardTarget *targetPtr) + /* Info about the content. */ { } @@ -224,28 +225,26 @@ TkSelUpdateClipboard( * * TkSelEventProc -- * - * This procedure is invoked whenever a selection-related - * event occurs. + * This procedure is invoked whenever a selection-related + * event occurs. * * Results: - * None. + * None. * * Side effects: - * Lots: depends on the type of event. + * Lots: depends on the type of event. * *-------------------------------------------------------------- */ void TkSelEventProc( - Tk_Window tkwin, /* Window for which event was - * targeted. */ - register XEvent *eventPtr) /* X event: either SelectionClear, - * SelectionRequest, or - * SelectionNotify. */ + Tk_Window tkwin, /* Window for which event was targeted. */ + register XEvent *eventPtr) /* X event: either SelectionClear, + * SelectionRequest, or SelectionNotify. */ { if (eventPtr->type == SelectionClear) { - TkSelClearSelection(tkwin, eventPtr); + TkSelClearSelection(tkwin, eventPtr); } } @@ -254,22 +253,22 @@ TkSelEventProc( * * TkSelPropProc -- * - * This procedure is invoked when property-change events - * occur on windows not known to the toolkit. This is a stub - * function under Windows. + * This procedure is invoked when property-change events + * occur on windows not known to the toolkit. This is a stub + * function under Windows. * * Results: - * None. + * None. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ void TkSelPropProc( - register XEvent *eventPtr) /* X PropertyChange event. */ + register XEvent *eventPtr) /* X PropertyChange event. */ { } @@ -278,20 +277,20 @@ TkSelPropProc( * * TkSuspendClipboard -- * - * Handle clipboard conversion as required by the suppend event. - * This function is also called on exit. + * Handle clipboard conversion as required by the suppend event. + * This function is also called on exit. * * Results: - * None. + * None. * * Side effects: - * The local scrap is moved to the global scrap. + * The local scrap is moved to the global scrap. * *---------------------------------------------------------------------- */ void -TkSuspendClipboard() +TkSuspendClipboard(void) { TkClipboardTarget *targetPtr; TkClipboardBuffer *cbPtr; @@ -302,50 +301,50 @@ TkSuspendClipboard() dispPtr = TkGetDisplayList(); if ((dispPtr == NULL) || !dispPtr->clipboardActive) { - return; + return; } for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL; - targetPtr = targetPtr->nextPtr) { - if (targetPtr->type == XA_STRING) - break; + targetPtr = targetPtr->nextPtr) { + if (targetPtr->type == XA_STRING) { + break; + } } if (targetPtr != NULL) { - Tcl_DString encodedText; - Tcl_DString unicodedText; - - length = 0; - for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL; - cbPtr = cbPtr->nextPtr) { - length += cbPtr->length; - } - - buffer = ckalloc(length); - buffPtr = buffer; - for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL; - cbPtr = cbPtr->nextPtr) { - for (p = cbPtr->buffer, endPtr = p + cbPtr->length; - p < endPtr; p++) { - if (*p == '\n') { - *buffPtr++ = '\r'; - } else { - *buffPtr++ = *p; - } - } - } - - ClearCurrentScrap(); - GetCurrentScrap(&scrapRef); - Tcl_UtfToExternalDString(TkMacOSXCarbonEncoding, buffer, - length, &encodedText); - PutScrapFlavor(scrapRef, 'TEXT', 0, - Tcl_DStringLength(&encodedText), - Tcl_DStringValue(&encodedText) ); - Tcl_DStringFree(&encodedText); + Tcl_DString encodedText, unicodedText; + + length = 0; + for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL; + cbPtr = cbPtr->nextPtr) { + length += cbPtr->length; + } + + buffer = ckalloc(length); + buffPtr = buffer; + for (cbPtr = targetPtr->firstBufferPtr; cbPtr != NULL; + cbPtr = cbPtr->nextPtr) { + for (p = cbPtr->buffer, endPtr = p + cbPtr->length; + p < endPtr; p++) { + if (*p == '\n') { + *buffPtr++ = '\r'; + } else { + *buffPtr++ = *p; + } + } + } + + ClearCurrentScrap(); + GetCurrentScrap(&scrapRef); + Tcl_UtfToExternalDString(TkMacOSXCarbonEncoding, buffer, length, + &encodedText); + PutScrapFlavor(scrapRef, 'TEXT', 0, Tcl_DStringLength(&encodedText), + Tcl_DStringValue(&encodedText)); + Tcl_DStringFree(&encodedText); /* - * Also put unicode data on scrap + * Also put unicode data on scrap. */ + Tcl_DStringInit(&unicodedText); Tcl_UtfToUniCharDString(buffer, length, &unicodedText); PutScrapFlavor(scrapRef, kScrapFlavorTypeUnicode, 0, @@ -353,19 +352,19 @@ TkSuspendClipboard() Tcl_DStringValue(&unicodedText)); Tcl_DStringFree(&unicodedText); - ckfree(buffer); + ckfree(buffer); } /* - * The system now owns the scrap. We tell Tk that it has + * The system now owns the scrap. We tell Tk that it has * lost the selection so that it will look for it the next time - * it needs it. (Window list NULL if quiting.) + * it needs it. (Window list NULL if quiting.) */ if (TkGetMainInfoList() != NULL) { - Tk_ClearSelection((Tk_Window) TkGetMainInfoList()->winPtr, - Tk_InternAtom((Tk_Window) TkGetMainInfoList()->winPtr, - "CLIPBOARD")); + Tk_ClearSelection((Tk_Window) TkGetMainInfoList()->winPtr, + Tk_InternAtom((Tk_Window) TkGetMainInfoList()->winPtr, + "CLIPBOARD")); } return; diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c index 9d65ac9..434f0ea 100644 --- a/macosx/tkMacOSXColor.c +++ b/macosx/tkMacOSXColor.c @@ -1,228 +1,527 @@ -/* +/* * tkMacOSXColor.c -- * - * This file maintains a database of color values for the Tk - * toolkit, in order to avoid round-trips to the server to - * map color names to pixel values. + * This file maintains a database of color values for the Tk + * toolkit, in order to avoid round-trips to the server to + * map color names to pixel values. * * Copyright (c) 1990-1994 The Regents of the University of California. * Copyright (c) 1994-1996 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2006-2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXColor.c,v 1.7 2006/11/03 03:05:03 das Exp $ + * RCS: @(#) $Id: tkMacOSXColor.c,v 1.8 2007/04/23 21:24:33 das Exp $ */ #include "tkMacOSXInt.h" #include "tkColor.h" -/* Define constants only available on Mac OS X 10.3 or later */ -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 - #define kThemeBrushAlternatePrimaryHighlightColor -5 +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 +/* Undocumented CG API for creating CGPattern from CGImage */ +extern CGPatternRef CGPatternCreateWithImage(CGImageRef img, int i) WEAK_IMPORT_ATTRIBUTE; #endif +struct SystemColorMapEntry { + const char *name; + ThemeBrush brush; + ThemeTextColor textColor; + ThemeBackgroundKind background; +}; /* unsigned char pixelCode; */ + /* - * Default Auxillary Control Record for all controls. This is cached once - * and is updated by the system. We use this to get the default system - * colors used by controls. + * Array of system color definitions: the array index is required to equal the + * color's (pixelCode - MIN_PIXELCODE), i.e. the array order needs to be kept + * in sync with the public pixel code values in tkMacOSXPort.h ! */ -/* - * Stubbed out for OS X -static AuxCtlHandle defaultAuxCtlHandle = NULL; -*/ + +#define MIN_PIXELCODE 30 +static const struct SystemColorMapEntry systemColorMap[] = { + { "Transparent", 0, 0, 0 }, /* 30: TRANSPARENT_PIXEL */ + { "Highlight", kThemeBrushPrimaryHighlightColor, 0, 0 }, /* 31: HIGHLIGHT_PIXEL */ + { "HighlightSecondary", kThemeBrushSecondaryHighlightColor, 0, 0 }, /* 32: HIGHLIGHT_SECONDARY_PIXEL */ + { "HighlightText", kThemeBrushBlack, 0, 0 }, /* 33: HIGHLIGHT_TEXT_PIXEL */ + { "HighlightAlternate", kThemeBrushAlternatePrimaryHighlightColor, 0, 0 }, /* 34: HIGHLIGHT_ALTERNATE_PIXEL */ + { "ButtonText", 0, kThemeTextColorPushButtonActive, 0 }, /* 35: CONTROL_TEXT_PIXEL */ + { "PrimaryHighlightColor", kThemeBrushPrimaryHighlightColor, 0, 0 }, /* 36 */ + { "ButtonFace", kThemeBrushButtonFaceActive, 0, 0 }, /* 37: CONTROL_BODY_PIXEL */ + { "SecondaryHighlightColor", kThemeBrushSecondaryHighlightColor, 0, 0 }, /* 38 */ + { "ButtonFrame", kThemeBrushButtonFrameActive, 0, 0 }, /* 39: CONTROL_FRAME_PIXEL */ + { "AlternatePrimaryHighlightColor", kThemeBrushAlternatePrimaryHighlightColor, 0, 0 }, /* 40 */ + { "WindowBody", kThemeBrushDocumentWindowBackground, 0, 0 }, /* 41: WINDOW_BODY_PIXEL */ + { "SheetBackground", kThemeBrushSheetBackground, 0, 0 }, /* 42 */ + { "MenuActive", kThemeBrushMenuBackgroundSelected, 0, 0 }, /* 43: MENU_ACTIVE_PIXEL */ + { "Black", kThemeBrushBlack, 0, 0 }, /* 44 */ + { "MenuActiveText", 0, kThemeTextColorMenuItemSelected, 0 }, /* 45: MENU_ACTIVE_TEXT_PIXEL */ + { "White", kThemeBrushWhite, 0, 0 }, /* 46 */ + { "Menu", kThemeBrushMenuBackground, 0, 0 }, /* 47: MENU_BACKGROUND_PIXEL */ + { "DialogBackgroundActive", kThemeBrushDialogBackgroundActive, 0, 0 }, /* 48 */ + { "MenuDisabled", 0, kThemeTextColorMenuItemDisabled, 0 }, /* 49: MENU_DISABLED_PIXEL */ + { "DialogBackgroundInactive", kThemeBrushDialogBackgroundInactive, 0, 0 }, /* 50 */ + { "MenuText", 0, kThemeTextColorMenuItemActive, 0 }, /* 51: MENU_TEXT_PIXEL */ + { "AppearanceColor", 0, 0, 0 }, /* 52: APPEARANCE_PIXEL */ + { "AlertBackgroundActive", kThemeBrushAlertBackgroundActive, 0, 0 }, /* 53 */ + { "AlertBackgroundInactive", kThemeBrushAlertBackgroundInactive, 0, 0 }, /* 54 */ + { "ModelessDialogBackgroundActive", kThemeBrushModelessDialogBackgroundActive, 0, 0 }, /* 55 */ + { "ModelessDialogBackgroundInactive", kThemeBrushModelessDialogBackgroundInactive, 0, 0 }, /* 56 */ + { "UtilityWindowBackgroundActive", kThemeBrushUtilityWindowBackgroundActive, 0, 0 }, /* 57 */ + { "UtilityWindowBackgroundInactive", kThemeBrushUtilityWindowBackgroundInactive, 0, 0 }, /* 58 */ + { "ListViewSortColumnBackground", kThemeBrushListViewSortColumnBackground, 0, 0 }, /* 59 */ + { "ListViewBackground", kThemeBrushListViewBackground, 0, 0 }, /* 60 */ + { "IconLabelBackground", kThemeBrushIconLabelBackground, 0, 0 }, /* 61 */ + { "ListViewSeparator", kThemeBrushListViewSeparator, 0, 0 }, /* 62 */ + { "ChasingArrows", kThemeBrushChasingArrows, 0, 0 }, /* 63 */ + { "DragHilite", kThemeBrushDragHilite, 0, 0 }, /* 64 */ + { "DocumentWindowBackground", kThemeBrushDocumentWindowBackground, 0, 0 }, /* 65 */ + { "FinderWindowBackground", kThemeBrushFinderWindowBackground, 0, 0 }, /* 66 */ + { "ScrollBarDelimiterActive", kThemeBrushScrollBarDelimiterActive, 0, 0 }, /* 67 */ + { "ScrollBarDelimiterInactive", kThemeBrushScrollBarDelimiterInactive, 0, 0 }, /* 68 */ + { "FocusHighlight", kThemeBrushFocusHighlight, 0, 0 }, /* 69 */ + { "PopupArrowActive", kThemeBrushPopupArrowActive, 0, 0 }, /* 70 */ + { "PopupArrowPressed", kThemeBrushPopupArrowPressed, 0, 0 }, /* 71 */ + { "PopupArrowInactive", kThemeBrushPopupArrowInactive, 0, 0 }, /* 72 */ + { "AppleGuideCoachmark", kThemeBrushAppleGuideCoachmark, 0, 0 }, /* 73 */ + { "IconLabelBackgroundSelected", kThemeBrushIconLabelBackgroundSelected, 0, 0 }, /* 74 */ + { "StaticAreaFill", kThemeBrushStaticAreaFill, 0, 0 }, /* 75 */ + { "ActiveAreaFill", kThemeBrushActiveAreaFill, 0, 0 }, /* 76 */ + { "ButtonFrameActive", kThemeBrushButtonFrameActive, 0, 0 }, /* 77 */ + { "ButtonFrameInactive", kThemeBrushButtonFrameInactive, 0, 0 }, /* 78 */ + { "ButtonFaceActive", kThemeBrushButtonFaceActive, 0, 0 }, /* 79 */ + { "ButtonFaceInactive", kThemeBrushButtonFaceInactive, 0, 0 }, /* 80 */ + { "ButtonFacePressed", kThemeBrushButtonFacePressed, 0, 0 }, /* 81 */ + { "ButtonActiveDarkShadow", kThemeBrushButtonActiveDarkShadow, 0, 0 }, /* 82 */ + { "ButtonActiveDarkHighlight", kThemeBrushButtonActiveDarkHighlight, 0, 0 }, /* 83 */ + { "ButtonActiveLightShadow", kThemeBrushButtonActiveLightShadow, 0, 0 }, /* 84 */ + { "ButtonActiveLightHighlight", kThemeBrushButtonActiveLightHighlight, 0, 0 }, /* 85 */ + { "ButtonInactiveDarkShadow", kThemeBrushButtonInactiveDarkShadow, 0, 0 }, /* 86 */ + { "ButtonInactiveDarkHighlight", kThemeBrushButtonInactiveDarkHighlight, 0, 0 }, /* 87 */ + { "ButtonInactiveLightShadow", kThemeBrushButtonInactiveLightShadow, 0, 0 }, /* 88 */ + { "ButtonInactiveLightHighlight", kThemeBrushButtonInactiveLightHighlight, 0, 0 }, /* 89 */ + { "ButtonPressedDarkShadow", kThemeBrushButtonPressedDarkShadow, 0, 0 }, /* 90 */ + { "ButtonPressedDarkHighlight", kThemeBrushButtonPressedDarkHighlight, 0, 0 }, /* 91 */ + { "ButtonPressedLightShadow", kThemeBrushButtonPressedLightShadow, 0, 0 }, /* 92 */ + { "ButtonPressedLightHighlight", kThemeBrushButtonPressedLightHighlight, 0, 0 }, /* 93 */ + { "BevelActiveLight", kThemeBrushBevelActiveLight, 0, 0 }, /* 94 */ + { "BevelActiveDark", kThemeBrushBevelActiveDark, 0, 0 }, /* 95 */ + { "BevelInactiveLight", kThemeBrushBevelInactiveLight, 0, 0 }, /* 96 */ + { "BevelInactiveDark", kThemeBrushBevelInactiveDark, 0, 0 }, /* 97 */ + { "NotificationWindowBackground", kThemeBrushNotificationWindowBackground, 0, 0 }, /* 98 */ + { "MovableModalBackground", kThemeBrushMovableModalBackground, 0, 0 }, /* 99 */ + { "SheetBackgroundOpaque", kThemeBrushSheetBackgroundOpaque, 0, 0 }, /* 100 */ + { "DrawerBackground", kThemeBrushDrawerBackground, 0, 0 }, /* 101 */ + { "ToolbarBackground", kThemeBrushToolbarBackground, 0, 0 }, /* 102 */ + { "SheetBackgroundTransparent", kThemeBrushSheetBackgroundTransparent, 0, 0 }, /* 103 */ + { "MenuBackground", kThemeBrushMenuBackground, 0, 0 }, /* 104 */ + { "Pixel", 0, 0, 0 }, /* 105: PIXEL_MAGIC */ + { "MenuBackgroundSelected", kThemeBrushMenuBackgroundSelected, 0, 0 }, /* 106 */ + { "ListViewOddRowBackground", kThemeBrushListViewOddRowBackground, 0, 0 }, /* 107 */ + { "ListViewEvenRowBackground", kThemeBrushListViewEvenRowBackground, 0, 0 }, /* 108 */ + { "ListViewColumnDivider", kThemeBrushListViewColumnDivider, 0, 0 }, /* 109 */ + { "BlackText", 0, kThemeTextColorBlack, 0 }, /* 110 */ + { "DialogActiveText", 0, kThemeTextColorDialogActive, 0 }, /* 111 */ + { "DialogInactiveText", 0, kThemeTextColorDialogInactive, 0 }, /* 112 */ + { "AlertActiveText", 0, kThemeTextColorAlertActive, 0 }, /* 113 */ + { "AlertInactiveText", 0, kThemeTextColorAlertInactive, 0 }, /* 114 */ + { "ModelessDialogActiveText", 0, kThemeTextColorModelessDialogActive, 0 }, /* 115 */ + { "ModelessDialogInactiveText", 0, kThemeTextColorModelessDialogInactive, 0 }, /* 116 */ + { "WindowHeaderActiveText", 0, kThemeTextColorWindowHeaderActive, 0 }, /* 117 */ + { "WindowHeaderInactiveText", 0, kThemeTextColorWindowHeaderInactive, 0 }, /* 118 */ + { "PlacardActiveText", 0, kThemeTextColorPlacardActive, 0 }, /* 119 */ + { "PlacardInactiveText", 0, kThemeTextColorPlacardInactive, 0 }, /* 120 */ + { "PlacardPressedText", 0, kThemeTextColorPlacardPressed, 0 }, /* 121 */ + { "PushButtonActiveText", 0, kThemeTextColorPushButtonActive, 0 }, /* 122 */ + { "PushButtonInactiveText", 0, kThemeTextColorPushButtonInactive, 0 }, /* 123 */ + { "PushButtonPressedText", 0, kThemeTextColorPushButtonPressed, 0 }, /* 124 */ + { "BevelButtonActiveText", 0, kThemeTextColorBevelButtonActive, 0 }, /* 125 */ + { "BevelButtonInactiveText", 0, kThemeTextColorBevelButtonInactive, 0 }, /* 126 */ + { "BevelButtonPressedText", 0, kThemeTextColorBevelButtonPressed, 0 }, /* 127 */ + { "PopupButtonActiveText", 0, kThemeTextColorPopupButtonActive, 0 }, /* 128 */ + { "PopupButtonInactiveText", 0, kThemeTextColorPopupButtonInactive, 0 }, /* 129 */ + { "PopupButtonPressedText", 0, kThemeTextColorPopupButtonPressed, 0 }, /* 130 */ + { "IconLabelText", 0, kThemeTextColorIconLabel, 0 }, /* 131 */ + { "ListViewText", 0, kThemeTextColorListView, 0 }, /* 132 */ + { "DocumentWindowTitleActiveText", 0, kThemeTextColorDocumentWindowTitleActive, 0 }, /* 133 */ + { "DocumentWindowTitleInactiveText", 0, kThemeTextColorDocumentWindowTitleInactive, 0 }, /* 134 */ + { "MovableModalWindowTitleActiveText", 0, kThemeTextColorMovableModalWindowTitleActive, 0 }, /* 135 */ + { "MovableModalWindowTitleInactiveText",0, kThemeTextColorMovableModalWindowTitleInactive, 0 }, /* 136 */ + { "UtilityWindowTitleActiveText", 0, kThemeTextColorUtilityWindowTitleActive, 0 }, /* 137 */ + { "UtilityWindowTitleInactiveText", 0, kThemeTextColorUtilityWindowTitleInactive, 0 }, /* 138 */ + { "PopupWindowTitleActiveText", 0, kThemeTextColorPopupWindowTitleActive, 0 }, /* 139 */ + { "PopupWindowTitleInactiveText", 0, kThemeTextColorPopupWindowTitleInactive, 0 }, /* 140 */ + { "RootMenuActiveText", 0, kThemeTextColorRootMenuActive, 0 }, /* 141 */ + { "RootMenuSelectedText", 0, kThemeTextColorRootMenuSelected, 0 }, /* 142 */ + { "RootMenuDisabledText", 0, kThemeTextColorRootMenuDisabled, 0 }, /* 143 */ + { "MenuItemActiveText", 0, kThemeTextColorMenuItemActive, 0 }, /* 144 */ + { "MenuItemSelectedText", 0, kThemeTextColorMenuItemSelected, 0 }, /* 145 */ + { "MenuItemDisabledText", 0, kThemeTextColorMenuItemDisabled, 0 }, /* 146 */ + { "PopupLabelActiveText", 0, kThemeTextColorPopupLabelActive, 0 }, /* 147 */ + { "PopupLabelInactiveText", 0, kThemeTextColorPopupLabelInactive, 0 }, /* 148 */ + { "TabFrontActiveText", 0, kThemeTextColorTabFrontActive, 0 }, /* 149 */ + { "TabNonFrontActiveText", 0, kThemeTextColorTabNonFrontActive, 0 }, /* 150 */ + { "TabNonFrontPressedText", 0, kThemeTextColorTabNonFrontPressed, 0 }, /* 151 */ + { "TabFrontInactiveText", 0, kThemeTextColorTabFrontInactive, 0 }, /* 152 */ + { "TabNonFrontInactiveText", 0, kThemeTextColorTabNonFrontInactive, 0 }, /* 153 */ + { "IconLabelSelectedText", 0, kThemeTextColorIconLabelSelected, 0 }, /* 154 */ + { "BevelButtonStickyActiveText", 0, kThemeTextColorBevelButtonStickyActive, 0 }, /* 155 */ + { "BevelButtonStickyInactiveText", 0, kThemeTextColorBevelButtonStickyInactive, 0 }, /* 156 */ + { "NotificationText", 0, kThemeTextColorNotification, 0 }, /* 157 */ + { "SystemDetailText", 0, kThemeTextColorSystemDetail, 0 }, /* 158 */ + { "WhiteText", 0, kThemeTextColorWhite, 0 }, /* 159 */ + { "TabPaneBackground", 0, 0, kThemeBackgroundTabPane }, /* 160 */ + { "PlacardBackground", 0, 0, kThemeBackgroundPlacard }, /* 161 */ + { "WindowHeaderBackground", 0, 0, kThemeBackgroundWindowHeader }, /* 162 */ + { "ListViewWindowHeaderBackground", 0, 0, kThemeBackgroundListViewWindowHeader }, /* 163 */ + { "SecondaryGroupBoxBackground", 0, 0, kThemeBackgroundSecondaryGroupBox }, /* 164 */ + { "MetalBackground", 0, 0, kThemeBackgroundMetal }, /* 165 */ + { NULL, 0, 0, 0 } +}; +#define MAX_PIXELCODE 165 /* - * Forward declarations for procedures defined later in this file: + *---------------------------------------------------------------------- + * + * GetThemeFromPixelCode -- + * + * When given a pixel code corresponding to a theme system color, + * set one of brush, textColor or background to the corresponding + * Appearance Mgr theme constant. + * + * Results: + * Returns false if not a real pixel, true otherwise. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- */ -static int GetControlPartColor _ANSI_ARGS_((short part, RGBColor *macColor)); -static int GetMenuPartColor _ANSI_ARGS_((int part, RGBColor *macColor)); -static int GetWindowPartColor _ANSI_ARGS_((short part, RGBColor *macColor)); +static int +GetThemeFromPixelCode(unsigned char code, ThemeBrush *brush, + ThemeTextColor *textColor, ThemeBackgroundKind *background) +{ + if (code >= MIN_PIXELCODE && code <= MAX_PIXELCODE && code != PIXEL_MAGIC) { + *brush = systemColorMap[code - MIN_PIXELCODE].brush; + *textColor = systemColorMap[code - MIN_PIXELCODE].textColor; + *background = systemColorMap[code - MIN_PIXELCODE].background; + } else { + *brush = 0; + *textColor = 0; + *background = 0; + } + if (!*brush && !*textColor && !*background && code != PIXEL_MAGIC) { + return false; + } else { + return true; + } +} /* *---------------------------------------------------------------------- * - * TkSetMacColor -- + * GetThemeColor -- * - * Populates a Macintosh RGBColor structure from a X style - * pixel value. + * Get RGB color for a given system color or pixel value. * * Results: - * Returns false if not a real pixel, true otherwise. + * OSStatus * * Side effects: - * The variable macColor is updated to the pixels value. + * None. * *---------------------------------------------------------------------- */ -int -TkSetMacColor( - unsigned long pixel, /* Pixel value to convert. */ - RGBColor *macColor) /* Mac color struct to modify. */ +static OSStatus +GetThemeColor(unsigned long pixel, ThemeBrush brush, ThemeTextColor textColor, + ThemeBackgroundKind background, RGBColor *c) { - OSStatus err; + OSStatus err = noErr; - switch (pixel >> 24) { - case HIGHLIGHT_PIXEL: - err = GetThemeBrushAsColor(kThemeBrushPrimaryHighlightColor, - 32, true, macColor); - if (err != noErr) { - LMGetHiliteRGB(macColor); - } - return true; - case HIGHLIGHT_SECONDARY_PIXEL: - err = GetThemeBrushAsColor(kThemeBrushSecondaryHighlightColor, - 32, true, macColor); - if (err != noErr) { - LMGetHiliteRGB(macColor); - } - return true; - case HIGHLIGHT_ALTERNATE_PIXEL: - err = GetThemeBrushAsColor(kThemeBrushAlternatePrimaryHighlightColor, - 32, true, macColor); - if (err != noErr) { - LMGetHiliteRGB(macColor); - } - return true; - case HIGHLIGHT_TEXT_PIXEL: - err = GetThemeBrushAsColor(kThemeBrushPrimaryHighlightColor, - 32, true, macColor); - if (err != noErr) { - LMGetHiliteRGB(macColor); - } - if ((macColor->red == 0) && (macColor->green == 0) - && (macColor->blue == 0)) { - macColor->red = macColor->green = macColor->blue = 0xFFFF; - } else { - macColor->red = macColor->green = macColor->blue = 0; - } - return true; - case CONTROL_TEXT_PIXEL: - GetControlPartColor(cTextColor, macColor); - return true; - case CONTROL_BODY_PIXEL: - GetControlPartColor(cBodyColor, macColor); - return true; - case CONTROL_FRAME_PIXEL: - GetControlPartColor(cFrameColor, macColor); - return true; - case WINDOW_BODY_PIXEL: - GetWindowPartColor(wContentColor, macColor); - return true; - case MENU_ACTIVE_PIXEL: - case MENU_ACTIVE_TEXT_PIXEL: - case MENU_BACKGROUND_PIXEL: - case MENU_DISABLED_PIXEL: - case MENU_TEXT_PIXEL: - return GetMenuPartColor((pixel >> 24), macColor); - case APPEARANCE_PIXEL: - return false; - case PIXEL_MAGIC: - default: - macColor->blue = (unsigned short) ((pixel & 0xFF) << 8); - macColor->green = (unsigned short) (((pixel >> 8) & 0xFF) << 8); - macColor->red = (unsigned short) (((pixel >> 16) & 0xFF) << 8); - return true; + if (brush) { + err = ChkErr(GetThemeBrushAsColor, + brush == kThemeBrushMenuBackgroundSelected ? + kThemeBrushFocusHighlight : brush, 32, true, c); + } else if (textColor) { + err = ChkErr(GetThemeTextColor, textColor, 32, true, c); + } else { + c->red = ((pixel >> 16) & 0xff) << 8; + c->green = ((pixel >> 8) & 0xff) << 8; + c->blue = ((pixel ) & 0xff) << 8; } + return err; } -#if !TK_DRAW_IN_CONTEXT /* *---------------------------------------------------------------------- * - * TkMacOSXCompareColors -- + * TkSetMacColor -- * - * On Mac, color codes may specify symbolic values like "highlight - * foreground", but we really need the actual values to compare. - * Maybe see also: "TIP #154: Add Named Colors to Tk". + * Populates a Macintosh RGBColor structure from a X style + * pixel value. * * Results: - * Returns true if both colors are the same, false otherwise. + * Returns false if not a real pixel, true otherwise. * * Side effects: - * None. + * The variable macColor is updated to the pixels value. * *---------------------------------------------------------------------- */ int -TkMacOSXCompareColors( - unsigned long c1, - unsigned long c2) +TkSetMacColor( + unsigned long pixel, /* Pixel value to convert. */ + RGBColor *macColor) /* Mac color struct to modify. */ { - RGBColor col1, col2; - return TkSetMacColor(c1,&col1) && - TkSetMacColor(c1,&col2) && - !memcmp(&col1,&col2,sizeof(col1)); + OSStatus err = -1; + ThemeBrush brush; + ThemeTextColor textColor; + ThemeBackgroundKind background; + + if (GetThemeFromPixelCode((pixel >> 24) & 0xff, &brush, &textColor, + &background)) { + err = ChkErr(GetThemeColor, pixel, brush, textColor, background, + macColor); + } + return (err == noErr); } -#endif /* !TK_DRAW_IN_CONTEXT */ /* *---------------------------------------------------------------------- * - * Stub functions -- + * TkMacOSXSetColorInPort -- * - * These functions are just stubs for functions that either - * don't make sense on the Mac or have yet to be implemented. + * Sets fore or back color in the current QD port from an X pixel + * value, and if the pixel code indicates a system color, sets + * the corresponding brush, textColor or background via + * Appearance mgr APIs. * * Results: - * None. + * None. * * Side effects: - * These calls do nothing - which may not be expected. + * If penPat is non-NULL it is set to the forground color/pattern. * *---------------------------------------------------------------------- */ -Status -XAllocColor( - Display *display, /* Display. */ - Colormap map, /* Not used. */ - XColor *colorPtr) /* XColor struct to modify. */ +void +TkMacOSXSetColorInPort(unsigned long pixel, int fg, PixPatHandle penPat) { - display->request++; - colorPtr->pixel = TkpGetPixel(colorPtr); - return 1; -} + OSStatus err; + RGBColor c; + ThemeBrush brush; + ThemeTextColor textColor; + ThemeBackgroundKind background; -Colormap -XCreateColormap( - Display *display, /* Display. */ - Window window, /* X window. */ - Visual *visual, /* Not used. */ - int alloc) /* Not used. */ -{ - static Colormap index = 1; - - /* - * Just return a new value each time. - */ - return index++; -} + if (GetThemeFromPixelCode((pixel >> 24) & 0xff, &brush, &textColor, + &background)) { + CGrafPtr port; -void -XFreeColormap( - Display* display, /* Display. */ - Colormap colormap) /* Colormap. */ -{ + GetPort(&port); + err = ChkErr(GetThemeColor, pixel, brush, textColor, background, &c); + if (err == noErr) { + if (fg) { + RGBForeColor(&c); + if (penPat) { + MakeRGBPat(penPat, &c); + } + } else { + RGBBackColor(&c); + } + } + err = -1; + if (brush) { + err = ChkErr(SetThemeBackground, + brush == kThemeBrushMenuBackgroundSelected ? + kThemeBrushFocusHighlight : brush, 32, true); + } else if (textColor && fg) { + err = ChkErr(SetThemeTextColor, textColor, 32, true); + } else if (background) { + Rect bounds; + + GetPortBounds(port, &bounds); + err = ChkErr(ApplyThemeBackground, background, &bounds, + kThemeStateActive, 32, true); + } + if (penPat && err == noErr && !textColor) { + GetPortBackPixPat(port, penPat); + } + } } + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXSetColorInContext -- + * + * Sets fill and stroke color in the given CG context from an X + * pixel value, or if the pixel code indicates a system color, + * sets the corresponding brush, textColor or background via + * HITheme APIs if available or Appearance mgr APIs. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ void -XFreeColors( - Display* display, /* Display. */ - Colormap colormap, /* Colormap. */ - unsigned long* pixels, /* Array of pixels. */ - int npixels, /* Number of pixels. */ - unsigned long planes) /* Number of pixel planes. */ +TkMacOSXSetColorInContext(unsigned long pixel, CGContextRef context) { - /* - * The Macintosh version of Tk uses TrueColor. Nothing - * needs to be done to release colors as there really is - * no colormap in the Tk sense. - */ + OSStatus err = -1; + RGBColor c; + ThemeBrush brush; + ThemeTextColor textColor; + ThemeBackgroundKind background; + + if (GetThemeFromPixelCode((pixel >> 24) & 0xff, &brush, &textColor, + &background)) { +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 + if (brush) { + if (1 +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 + && HIThemeSetFill != NULL && HIThemeSetStroke != NULL +#endif + ) { + err = ChkErr(HIThemeSetFill, brush, NULL, context, + kHIThemeOrientationNormal); + if (err == noErr) { + err = ChkErr(HIThemeSetStroke, brush, NULL, context, + kHIThemeOrientationNormal); + } + } + } else if (textColor) { + if (1 +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 + && HIThemeSetTextFill != NULL +#endif + ) { + err = ChkErr(HIThemeSetTextFill, textColor, NULL, context, + kHIThemeOrientationNormal); + } + } else +#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 */ +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 + if (background) { + if (1 +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1030 + && CGContextGetClipBoundingBox != NULL + && HIThemeApplyBackground != NULL + && &kHIToolboxVersionNumber != NULL /* c.f. QA1377 */ + && kHIToolboxVersionNumber >= kHIToolboxVersionNumber10_3 +#endif + ) { + CGRect rect = CGContextGetClipBoundingBox(context); + HIThemeBackgroundDrawInfo info = { 0, kThemeStateActive, + background }; + + err = ChkErr(HIThemeApplyBackground, &rect, &info, context, + kHIThemeOrientationNormal); + } + } +#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */ + if (err == noErr) { + return; + } +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 + /* + * Convert Appearance theme pattern to CGPattern: + */ + if ((brush || background) && CGPatternCreateWithImage != NULL) { + static PixPatHandle pixpat = NULL; + static GWorldPtr patGWorld = NULL; + static uint32_t bitmapInfo = 0; + const short patDim = 16; + const Rect bounds = {0, 0, patDim, patDim}; + CGrafPtr savePort; + Boolean portChanged; + PixMapHandle pixmap; + long rowbytes; + CGImageRef img; + CGColorSpaceRef rgbCspace; + CGDataProviderRef provider; + + if (!pixpat) { + pixpat = NewPixPat(); + err = ChkErr(NewGWorld, &patGWorld, 32, &bounds, NULL, NULL, 0 +#ifdef __LITTLE_ENDIAN__ + | kNativeEndianPixMap +#endif + ); + if (!pixpat || err != noErr || !patGWorld) { + Tcl_Panic("TkMacOSXSetColorInContext(): " + "pattern initialization failed !"); + } + bitmapInfo = +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 + (1 +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 + && &kHIToolboxVersionNumber != NULL + && kHIToolboxVersionNumber >= kHIToolboxVersionNumber10_4 +#endif + ) ? kCGBitmapByteOrder32Host : +#endif + 0; + } + portChanged = QDSwapPort(patGWorld, &savePort); + TkMacOSXSetColorInPort(pixel, 1, pixpat); +#ifdef TK_MAC_DEBUG + Rect patBounds; + GetPixBounds((**pixpat).patMap, &patBounds); + if (patBounds.right > patDim || patBounds.bottom > patDim) { + Tcl_Panic("TkMacOSXSetColorInContext(): " + "pattern larger than expected !"); + } +#endif /* TK_MAC_DEBUG */ + FillCRect(&bounds, pixpat); + if (portChanged) { + QDSwapPort(savePort, NULL); + } + pixmap = GetPortPixMap(patGWorld); + rowbytes = GetPixRowBytes(pixmap); + provider = CGDataProviderCreateWithData(&patGWorld, + GetPixBaseAddr(pixmap), rowbytes * patDim, NULL); + rgbCspace = CGColorSpaceCreateDeviceRGB(); + img = CGImageCreate(patDim, patDim, 8, 32, + rowbytes, rgbCspace, kCGImageAlphaFirst | bitmapInfo, + provider, NULL, 0, kCGRenderingIntentDefault); + CGColorSpaceRelease(rgbCspace); + CGDataProviderRelease(provider); + if (img) { + CGPatternRef pat = CGPatternCreateWithImage(img, 2); + CGColorSpaceRef patCSpace = CGColorSpaceCreatePattern(NULL); + const float alpha = 1; + + CGContextSetFillColorSpace(context, patCSpace); + CGContextSetFillPattern(context, pat, &alpha); + CGContextSetStrokeColorSpace(context, patCSpace); + CGContextSetStrokePattern(context, pat, &alpha); + CGColorSpaceRelease(patCSpace); + CGPatternRelease(pat); + CGImageRelease(img); + return; + } + } +#endif /* MAC_OS_X_VERSION_MIN_REQUIRED < 1040 */ + err = ChkErr(GetThemeColor, pixel, brush, textColor, background, &c); + if (err == noErr) { + double r = c.red / 65535.0; + double g = c.green / 65535.0; + double b = c.blue / 65535.0; + + CGContextSetRGBFillColor(context, r, g, b, 1.0); + CGContextSetRGBStrokeColor(context, r, g, b, 1.0); + } + } else if (((pixel >> 24) & 0xff) == TRANSPARENT_PIXEL) { + CGContextSetRGBFillColor(context, 0.0, 0.0, 0.0, 0.0); + CGContextSetRGBStrokeColor(context, 0.0, 0.0, 0.0, 0.0); + } } /* @@ -230,24 +529,24 @@ XFreeColors( * * TkpGetColor -- * - * Allocate a new TkColor for the color with the given name. + * Allocate a new TkColor for the color with the given name. * * Results: - * Returns a newly allocated TkColor, or NULL on failure. + * Returns a newly allocated TkColor, or NULL on failure. * * Side effects: - * May invalidate the colormap cache associated with tkwin upon - * allocating a new colormap entry. Allocates a new TkColor - * structure. + * May invalidate the colormap cache associated with tkwin upon + * allocating a new colormap entry. Allocates a new TkColor + * structure. * *---------------------------------------------------------------------- */ TkColor * TkpGetColor( - Tk_Window tkwin, /* Window in which color will be used. */ - Tk_Uid name) /* Name of color to allocated (in form - * suitable for passing to XParseColor). */ + Tk_Window tkwin, /* Window in which color will be used. */ + Tk_Uid name) /* Name of color to allocated (in form + * suitable for passing to XParseColor). */ { Display *display = Tk_Display(tkwin); Colormap colormap = Tk_Colormap(tkwin); @@ -255,116 +554,43 @@ TkpGetColor( XColor color; /* - * Check to see if this is a system color. Otherwise, XParseColor + * Check to see if this is a system color. Otherwise, XParseColor * will do all the work. */ if (strncasecmp(name, "system", 6) == 0) { - OSStatus err; - int foundSystemColor = false; - RGBColor rgbValue; - char pixelCode = 0; - - if (!strcasecmp(name+6, "Highlight")) { - err = GetThemeBrushAsColor(kThemeBrushPrimaryHighlightColor, - 32, true, &rgbValue); - if (err != noErr) { - LMGetHiliteRGB(&rgbValue); - } - pixelCode = HIGHLIGHT_PIXEL; - foundSystemColor = true; - } else if (!strcasecmp(name+6, "HighlightSecondary")) { - err = GetThemeBrushAsColor(kThemeBrushSecondaryHighlightColor, - 32, true, &rgbValue); - if (err != noErr) { - LMGetHiliteRGB(&rgbValue); - } - pixelCode = HIGHLIGHT_SECONDARY_PIXEL; - foundSystemColor = true; - } else if (!strcasecmp(name+6, "HighlightAlternate")) { - err = GetThemeBrushAsColor(kThemeBrushAlternatePrimaryHighlightColor, - 32, true, &rgbValue); - if (err != noErr) { - LMGetHiliteRGB(&rgbValue); - } - pixelCode = HIGHLIGHT_ALTERNATE_PIXEL; - foundSystemColor = true; - } else if (!strcasecmp(name+6, "HighlightText")) { - err = GetThemeBrushAsColor(kThemeBrushPrimaryHighlightColor, - 32, true, &rgbValue); - if (err != noErr) { - LMGetHiliteRGB(&rgbValue); + Tcl_Obj *strPtr = Tcl_NewStringObj(name+6, -1); + int idx, result; + + result = Tcl_GetIndexFromObjStruct(NULL, strPtr, systemColorMap, + sizeof(struct SystemColorMapEntry), NULL, TCL_EXACT, &idx); + Tcl_DecrRefCount(strPtr); + if (result == TCL_OK) { + OSStatus err; + RGBColor c; + unsigned char pixelCode = idx + MIN_PIXELCODE; + ThemeBrush brush = systemColorMap[idx].brush; + ThemeTextColor textColor = systemColorMap[idx].textColor; + ThemeBackgroundKind background = systemColorMap[idx].background; + + err = ChkErr(GetThemeColor, 0, brush, textColor, background, &c); + if (err == noErr) { + color.red = c.red; + color.green = c.green; + color.blue = c.blue; + color.pixel = ((((((pixelCode << 8) + | ((color.red >> 8) & 0xff)) << 8) + | ((color.green >> 8) & 0xff)) << 8) + | ((color.blue >> 8) & 0xff)); + goto validXColor; } - if ((rgbValue.red == 0) && (rgbValue.green == 0) - && (rgbValue.blue == 0)) { - rgbValue.red = rgbValue.green = rgbValue.blue = 0xFFFF; - } else { - rgbValue.red = rgbValue.green = rgbValue.blue = 0; - } - pixelCode = HIGHLIGHT_TEXT_PIXEL; - foundSystemColor = true; - } else if (!strcasecmp(name+6, "ButtonText")) { - GetControlPartColor(cTextColor, &rgbValue); - pixelCode = CONTROL_TEXT_PIXEL; - foundSystemColor = true; - } else if (!strcasecmp(name+6, "ButtonFace")) { - GetControlPartColor(cBodyColor, &rgbValue); - pixelCode = CONTROL_BODY_PIXEL; - foundSystemColor = true; - } else if (!strcasecmp(name+6, "ButtonFrame")) { - GetControlPartColor(cFrameColor, &rgbValue); - pixelCode = CONTROL_FRAME_PIXEL; - foundSystemColor = true; - } else if (!strcasecmp(name+6, "WindowBody")) { - GetWindowPartColor(wContentColor, &rgbValue); - pixelCode = WINDOW_BODY_PIXEL; - foundSystemColor = true; - } else if (!strcasecmp(name+6, "MenuActive")) { - GetMenuPartColor(MENU_ACTIVE_PIXEL, &rgbValue); - pixelCode = MENU_ACTIVE_PIXEL; - foundSystemColor = true; - } else if (!strcasecmp(name+6, "MenuActiveText")) { - GetMenuPartColor(MENU_ACTIVE_TEXT_PIXEL, &rgbValue); - pixelCode = MENU_ACTIVE_TEXT_PIXEL; - foundSystemColor = true; - } else if (!strcasecmp(name+6, "Menu")) { - GetMenuPartColor(MENU_BACKGROUND_PIXEL, &rgbValue); - pixelCode = MENU_BACKGROUND_PIXEL; - foundSystemColor = true; - } else if (!strcasecmp(name+6, "MenuDisabled")) { - GetMenuPartColor(MENU_DISABLED_PIXEL, &rgbValue); - pixelCode = MENU_DISABLED_PIXEL; - foundSystemColor = true; - } else if (!strcasecmp(name+6, "MenuText")) { - GetMenuPartColor(MENU_TEXT_PIXEL, &rgbValue); - pixelCode = MENU_TEXT_PIXEL; - foundSystemColor = true; - } else if (!strcasecmp(name+6, "AppearanceColor")) { - color.red = 0; - color.green = 0; - color.blue = 0; - pixelCode = APPEARANCE_PIXEL; - foundSystemColor = true; - } - - if (foundSystemColor) { - color.red = rgbValue.red; - color.green = rgbValue.green; - color.blue = rgbValue.blue; - color.pixel = ((((((pixelCode << 8) - | ((color.red >> 8) & 0xff)) << 8) - | ((color.green >> 8) & 0xff)) << 8) - | ((color.blue >> 8) & 0xff)); - - tkColPtr = (TkColor *) ckalloc(sizeof(TkColor)); - tkColPtr->color = color; - return tkColPtr; - } + } } - + if (XParseColor(display, colormap, name, &color) == 0) { - return (TkColor *) NULL; + return (TkColor *) NULL; } - + +validXColor: tkColPtr = (TkColor *) ckalloc(sizeof(TkColor)); tkColPtr->color = color; @@ -376,28 +602,28 @@ TkpGetColor( * * TkpGetColorByValue -- * - * Given a desired set of red-green-blue intensities for a color, - * locate a pixel value to use to draw that color in a given - * window. + * Given a desired set of red-green-blue intensities for a color, + * locate a pixel value to use to draw that color in a given + * window. * * Results: - * The return value is a pointer to an TkColor structure that - * indicates the closest red, blue, and green intensities available - * to those specified in colorPtr, and also specifies a pixel - * value to use to draw in that color. + * The return value is a pointer to an TkColor structure that + * indicates the closest red, blue, and green intensities available + * to those specified in colorPtr, and also specifies a pixel + * value to use to draw in that color. * * Side effects: - * May invalidate the colormap cache for the specified window. - * Allocates a new TkColor structure. + * May invalidate the colormap cache for the specified window. + * Allocates a new TkColor structure. * *---------------------------------------------------------------------- */ TkColor * TkpGetColorByValue( - Tk_Window tkwin, /* Window in which color will be used. */ - XColor *colorPtr) /* Red, green, and blue fields indicate - * desired color. */ + Tk_Window tkwin, /* Window in which color will be used. */ + XColor *colorPtr) /* Red, green, and blue fields indicate + * desired color. */ { TkColor *tkColPtr = (TkColor *) ckalloc(sizeof(TkColor)); @@ -408,123 +634,98 @@ TkpGetColorByValue( return tkColPtr; } +#if !TK_DRAW_IN_CONTEXT /* *---------------------------------------------------------------------- * - * GetControlPartColor -- + * TkMacOSXCompareColors -- * - * Given a part number this function will return the standard - * system default color for that part. On MacOS X this uses the - * Theme Brushes to find the active color, though for now, only - * the "Text Color" is supported. + * On Mac, color codes may specify symbolic values like "highlight + * foreground", but we really need the actual values to compare. + * Maybe see also: "TIP #154: Add Named Colors to Tk". * * Results: - * True if a color is found, false otherwise. + * Returns true if both colors are the same, false otherwise. * * Side effects: - * If a color is found then the RGB variable will be changed to - * the parts color. + * None. * *---------------------------------------------------------------------- */ -static int -GetControlPartColor( - short part, /* Part code. */ - RGBColor *macColor) /* Pointer to Mac color. */ +int +TkMacOSXCompareColors( + unsigned long c1, + unsigned long c2) { - int retVal = false; - OSErr err; - - switch (part) { - case cTextColor: - err = GetThemeTextColor(kThemeTextColorPushButtonActive, 32, - true, macColor); - if (err == noErr) { - retVal = true; - } - break; - default: - retVal = false; - } - return retVal; + RGBColor col1, col2; + return TkSetMacColor(c1,&col1) && + TkSetMacColor(c1,&col2) && + !memcmp(&col1,&col2,sizeof(col1)); } +#endif /* !TK_DRAW_IN_CONTEXT */ /* *---------------------------------------------------------------------- * - * GetWindowPartColor -- + * Stub functions -- * - * Given a part number this function will return the standard - * system default color for that part. It does this by looking - * in the system's 'wctb' resource. + * These functions are just stubs for functions that either + * don't make sense on the Mac or have yet to be implemented. * * Results: - * True if a color is found, false otherwise. + * None. * * Side effects: - * If a color is found then the RGB variable will be changed to - * the parts color. + * These calls do nothing - which may not be expected. * *---------------------------------------------------------------------- */ -static int -GetWindowPartColor( - short part, /* Part code. */ - RGBColor *macColor) /* Pointer to Mac color. */ +Status +XAllocColor( + Display *display, /* Display. */ + Colormap map, /* Not used. */ + XColor *colorPtr) /* XColor struct to modify. */ { - short index; - WCTabHandle wcTab; + display->request++; + colorPtr->pixel = TkpGetPixel(colorPtr); + return 1; +} - if (part == wContentColor) { - GetThemeBrushAsColor(kThemeBrushDocumentWindowBackground, - 0xFFFF, true, macColor); - return true; - } else { - wcTab = (WCTabHandle) GetResource('wctb', 0); - if(wcTab && (ResError() == noErr)) { - for(index = 0; index <= (**wcTab).ctSize; index++) { - if((**wcTab).ctTable[index].value == part) { - *macColor = (**wcTab).ctTable[index].rgb; - return true; - } - } - } - return false; - } +Colormap +XCreateColormap( + Display *display, /* Display. */ + Window window, /* X window. */ + Visual *visual, /* Not used. */ + int alloc) /* Not used. */ +{ + static Colormap index = 1; + + /* + * Just return a new value each time. + */ + return index++; } - -/* - *---------------------------------------------------------------------- - * - * GetMenuPartColor -- - * - * Given a magic pixel value, returns the RGB color associated - * with it by looking the value up in the system's 'mctb' resource. - * - * Results: - * True if a color is found, false otherwise. - * - * Side effects: - * If a color is found then the RGB variable will be changed to - * the parts color. - * - *---------------------------------------------------------------------- - */ -static int -GetMenuPartColor( - int pixel, /* The magic pixel value */ - RGBColor *macColor) /* Pointer to Mac color */ +void +XFreeColormap( + Display* display, /* Display. */ + Colormap colormap) /* Colormap. */ +{ +} + +void +XFreeColors( + Display* display, /* Display. */ + Colormap colormap, /* Colormap. */ + unsigned long* pixels, /* Array of pixels. */ + int npixels, /* Number of pixels. */ + unsigned long planes) /* Number of pixel planes. */ { - - /* Under Appearance, we don't want to set any menu colors when we - are asked for the standard menu colors. So we return false (which - means don't use this color... */ - - macColor->red = 0xFFFF; - macColor->green = 0; - macColor->blue = 0; - return false; + /* + * The Macintosh version of Tk uses TrueColor. Nothing + * needs to be done to release colors as there really is + * no colormap in the Tk sense. + */ } diff --git a/macosx/tkMacOSXConfig.c b/macosx/tkMacOSXConfig.c index fa1e62e..197cfbe 100644 --- a/macosx/tkMacOSXConfig.c +++ b/macosx/tkMacOSXConfig.c @@ -1,8 +1,8 @@ -/* +/* * tkMacOSXConfig.c -- * - * This module implements the Macintosh system defaults for - * the configuration package. + * This module implements the Macintosh system defaults for + * the configuration package. * * Copyright (c) 1997 by Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. @@ -10,7 +10,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXConfig.c,v 1.3 2006/03/24 14:58:01 das Exp $ + * RCS: @(#) $Id: tkMacOSXConfig.c,v 1.4 2007/04/23 21:24:33 das Exp $ */ #include "tkInt.h" @@ -21,25 +21,25 @@ * * TkpGetSystemDefault -- * - * Given a dbName and className for a configuration option, - * return a string representation of the option. + * Given a dbName and className for a configuration option, + * return a string representation of the option. * * Results: - * Returns a Tk_Uid that is the string identifier that identifies - * this option. Returns NULL if there are no system defaults - * that match this pair. + * Returns a Tk_Uid that is the string identifier that identifies + * this option. Returns NULL if there are no system defaults + * that match this pair. * * Side effects: - * None, once the package is initialized. + * None, once the package is initialized. * *---------------------------------------------------------------------- */ Tcl_Obj * TkpGetSystemDefault( - Tk_Window tkwin, /* A window to use. */ - CONST char *dbName, /* The option database name. */ - CONST char *className) /* The name of the option class. */ + Tk_Window tkwin, /* A window to use. */ + CONST char *dbName, /* The option database name. */ + CONST char *className) /* The name of the option class. */ { return NULL; } diff --git a/macosx/tkMacOSXCursor.c b/macosx/tkMacOSXCursor.c index 571f5b6..bbb72e1 100644 --- a/macosx/tkMacOSXCursor.c +++ b/macosx/tkMacOSXCursor.c @@ -1,15 +1,16 @@ -/* +/* * tkMacOSXCursor.c -- * - * This file contains Macintosh specific cursor related routines. + * This file contains Macintosh specific cursor related routines. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2006-2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXCursor.c,v 1.10 2007/04/21 19:06:37 hobbs Exp $ + * RCS: @(#) $Id: tkMacOSXCursor.c,v 1.11 2007/04/23 21:24:33 das Exp $ */ #include "tkMacOSXInt.h" @@ -20,10 +21,11 @@ * color resource cursors, & normal cursors. */ -#define THEME 0 /* Theme cursors */ -#define ANIMATED 1 /* Animated theme cursors */ -#define COLOR 2 /* Cursors of type crsr. */ -#define NORMAL 3 /* Cursors of type CURS. */ +#define NONE -1 /* Hidden cursor */ +#define THEME 0 /* Theme cursors */ +#define ANIMATED 1 /* Animated theme cursors */ +#define COLOR 2 /* Cursors of type crsr. */ +#define NORMAL 3 /* Cursors of type CURS. */ /* * The following data structure contains the system specific data @@ -31,14 +33,14 @@ */ typedef struct { - TkCursor info; /* Generic cursor info used by tkCursor.c */ - Handle macCursor; /* Resource containing Macintosh cursor. - * For theme cursors, this is -1. */ - int type; /* Type of Mac cursor: for theme cursors - * this is the theme cursor constant, - * otherwise one of crsr or CURS */ - int count; /* For animating cursors, the count for the - cursor. */ + TkCursor info; /* Generic cursor info used by tkCursor.c */ + Handle macCursor; /* Resource containing Macintosh cursor. + * For theme cursors, this is -1. */ + int type; /* Type of Mac cursor: for theme cursors + * this is the theme cursor constant, + * otherwise one of crsr or CURS */ + int count; /* For animating cursors, the count for the + * cursor. */ } TkMacOSXCursor; /* @@ -47,119 +49,128 @@ typedef struct { */ struct CursorName { - char *name; + const char *name; int id; }; +static struct CursorName noneCursorName = {"none", 0}; + static struct CursorName themeCursorNames[] = { - {"ibeam", kThemeIBeamCursor}, - {"text", kThemeIBeamCursor}, - {"xterm", kThemeIBeamCursor}, - {"cross", kThemeCrossCursor}, - {"crosshair", kThemeCrossCursor}, - {"cross-hair", kThemeCrossCursor}, - {"plus", kThemePlusCursor}, - {"arrow", kThemeArrowCursor}, - {"closedhand", kThemeClosedHandCursor}, - {"openhand", kThemeOpenHandCursor}, - {"pointinghand", kThemePointingHandCursor}, - {NULL, 0} + {"arrow", kThemeArrowCursor}, + {"copyarrow", kThemeCopyArrowCursor}, + {"aliasarrow", kThemeAliasArrowCursor}, + {"contextualmenuarrow", kThemeContextualMenuArrowCursor}, + {"ibeam", kThemeIBeamCursor}, + {"text", kThemeIBeamCursor}, + {"xterm", kThemeIBeamCursor}, + {"cross", kThemeCrossCursor}, + {"crosshair", kThemeCrossCursor}, + {"cross-hair", kThemeCrossCursor}, + {"plus", kThemePlusCursor}, + {"closedhand", kThemeClosedHandCursor}, + {"openhand", kThemeOpenHandCursor}, + {"pointinghand", kThemePointingHandCursor}, + {"resizeleft", kThemeResizeLeftCursor}, + {"resizeright", kThemeResizeRightCursor}, + {"resizeleftright", kThemeResizeLeftRightCursor}, + {"resizeup", kThemeResizeUpCursor}, + {"resizedown", kThemeResizeDownCursor}, + {"resizeupdown", kThemeResizeUpDownCursor}, + {"notallowed", kThemeNotAllowedCursor}, + {"poof", kThemePoofCursor}, + {NULL, 0} }; static struct CursorName animatedThemeCursorNames[] = { - {"watch", kThemeWatchCursor}, - {"countinguphand", kThemeCountingUpHandCursor}, + {"watch", kThemeWatchCursor}, + {"countinguphand", kThemeCountingUpHandCursor}, {"countingdownhand", kThemeCountingDownHandCursor}, {"countingupanddownhand", kThemeCountingUpAndDownHandCursor}, - {"spinning", kThemeSpinningCursor}, - {NULL, 0} + {"spinning", kThemeSpinningCursor}, + {NULL, 0} }; /* * Declarations of static variables used in this file. */ -static TkMacOSXCursor * gCurrentCursor = NULL; /* A pointer to the current - * cursor. */ -static int gResizeOverride = false; /* A boolean indicating whether - * we should use the resize - * cursor during installations. */ -static int gTkOwnsCursor = true; /* A boolean indicating whether - Tk owns the cursor. If not (for - instance, in the case where a Tk - window is embedded in another app's - window, and the cursor is out of - the tk window, we will not attempt - to adjust the cursor */ +static TkMacOSXCursor * gCurrentCursor = NULL; /* A pointer to the current + * cursor. */ +static int gResizeOverride = false; /* A boolean indicating whether + * we should use the resize + * cursor during installations. */ +static int gTkOwnsCursor = true; /* A boolean indicating whether + * Tk owns the cursor. If not (for + * instance, in the case where a Tk + * window is embedded in another app's + * window, and the cursor is out of + * the tk window, we will not attempt + * to adjust the cursor */ /* * Declarations of procedures local to this file */ -static void FindCursorByName _ANSI_ARGS_ ((TkMacOSXCursor *macCursorPtr, - CONST char *string)); +static void FindCursorByName(TkMacOSXCursor *macCursorPtr, const char *string); + /* *---------------------------------------------------------------------- * * FindCursorByName -- * - * Retrieve a system cursor by name, and fill the macCursorPtr - * structure. If the cursor cannot be found, the macCursor field - * will be NULL. The function first attempts to load a color - * cursor. If that fails it will attempt to load a black & white - * cursor. + * Retrieve a system cursor by name, and fill the macCursorPtr + * structure. If the cursor cannot be found, the macCursor field + * will be NULL. The function first attempts to load a color + * cursor. If that fails it will attempt to load a black & white + * cursor. * * Results: - * Fills the macCursorPtr record. + * Fills the macCursorPtr record. * * Side effects: - * None + * None * *---------------------------------------------------------------------- */ - -void + +void FindCursorByName( TkMacOSXCursor *macCursorPtr, - CONST char *string) + const char *string) { Handle resource; Str255 curName; int destWrote, inCurLen; + Tcl_Encoding encoding; inCurLen = strlen(string); if (inCurLen > 255) { - return; + return; } /* * macRoman is the encoding that the resource fork uses. */ - Tcl_UtfToExternal(NULL, Tcl_GetEncoding(NULL, "macRoman"), string, - inCurLen, 0, NULL, - (char *) &curName[1], - 255, NULL, &destWrote, NULL); /* Internalize native */ + encoding = Tcl_GetEncoding(NULL, "macRoman"); + Tcl_UtfToExternal(NULL, encoding, string, inCurLen, 0, NULL, + (char *) &curName[1], 255, NULL, &destWrote, NULL); curName[0] = destWrote; + Tcl_FreeEncoding(encoding); resource = GetNamedResource('crsr', curName); - - if (resource != NULL) { - short id; - Str255 theName; - ResType theType; - - HLock(resource); - GetResInfo(resource, &id, &theType, theName); - HUnlock(resource); - macCursorPtr->macCursor = (Handle) GetCCursor(id); - macCursorPtr->type = COLOR; - } - - if (resource == NULL) { - macCursorPtr->macCursor = GetNamedResource('CURS', curName); - macCursorPtr->type = NORMAL; + if (resource) { + short id; + Str255 theName; + ResType theType; + + GetResInfo(resource, &id, &theType, theName); + macCursorPtr->macCursor = (Handle) GetCCursor(id); + macCursorPtr->type = COLOR; + } else { + macCursorPtr->macCursor = GetNamedResource('CURS', curName); + macCursorPtr->type = NORMAL; } } @@ -168,28 +179,28 @@ FindCursorByName( * * TkGetCursorByName -- * - * Retrieve a system cursor by name. + * Retrieve a system cursor by name. * * Results: - * Returns a new cursor, or NULL on errors. + * Returns a new cursor, or NULL on errors. * * Side effects: - * Allocates a new cursor. + * Allocates a new cursor. * *---------------------------------------------------------------------- */ TkCursor * TkGetCursorByName( - Tcl_Interp *interp, /* Interpreter to use for error reporting. */ - Tk_Window tkwin, /* Window in which cursor will be used. */ - Tk_Uid string) /* Description of cursor. See manual entry - * for details on legal syntax. */ + Tcl_Interp *interp, /* Interpreter to use for error reporting. */ + Tk_Window tkwin, /* Window in which cursor will be used. */ + Tk_Uid string) /* Description of cursor. See manual entry + * for details on legal syntax. */ { struct CursorName *namePtr; TkMacOSXCursor *macCursorPtr; int count = -1; - + macCursorPtr = (TkMacOSXCursor *) ckalloc(sizeof(TkMacOSXCursor)); macCursorPtr->info.cursor = (Tk_Cursor) macCursorPtr; @@ -199,71 +210,67 @@ TkGetCursorByName( * attempt to load the cursor as a named Mac resource. */ - for (namePtr = themeCursorNames; namePtr->name != NULL; namePtr++) { - if (strcmp(namePtr->name, string) == 0) { - macCursorPtr->count = -1; - macCursorPtr->macCursor = (Handle) namePtr; - macCursorPtr->type = THEME; - break; - } + if (strcmp(noneCursorName.name, string) == 0) { + namePtr = &noneCursorName; + macCursorPtr->type = NONE; + } else { + for (namePtr = themeCursorNames; namePtr->name != NULL; namePtr++) { + if (strcmp(namePtr->name, string) == 0) { + macCursorPtr->type = THEME; + break; + } + } } if (namePtr->name == NULL) { - for (namePtr = animatedThemeCursorNames; - namePtr->name != NULL; namePtr++) { - int namelen = strlen (namePtr->name); - if (strncmp(namePtr->name, string, namelen) == 0) { - const char *numPtr = string + namelen; - if (*numPtr == '\0') { - count = -1; - } else { - int result; - result = Tcl_GetInt(NULL, numPtr, &count); - if (result != TCL_OK) { - continue; - } - } - macCursorPtr->macCursor = (Handle) namePtr; - macCursorPtr->type = ANIMATED; - macCursorPtr->count = count; - break; - } - } + for (namePtr = animatedThemeCursorNames; + namePtr->name != NULL; namePtr++) { + int namelen = strlen (namePtr->name); + if (strncmp(namePtr->name, string, namelen) == 0) { + const char *numPtr = string + namelen; + if (*numPtr) { + int result = Tcl_GetInt(NULL, numPtr, &count); + if (result != TCL_OK) { + continue; + } + } + macCursorPtr->type = ANIMATED; + break; + } + } } - - - if (namePtr->name == NULL) { - FindCursorByName(macCursorPtr, string); - - if (macCursorPtr->macCursor == NULL) { - CONST char **argv; - int argc, err; - - /* - * The user may be trying to specify an XCursor with fore - * & back colors. We don't want this to be an error, so pick - * off the first word, and try again. - */ - - err = Tcl_SplitList(interp, string, &argc, &argv); - if (err == TCL_OK ) { - if (argc > 1) { - FindCursorByName(macCursorPtr, argv[0]); - } - - ckfree((char *) argv); - } - } + if (namePtr->name != NULL) { + macCursorPtr->macCursor = (Handle) namePtr; + macCursorPtr->count = count; + } else { + FindCursorByName(macCursorPtr, string); + + if (macCursorPtr->macCursor == NULL) { + const char **argv; + int argc; + + /* + * The user may be trying to specify an XCursor with fore + * & back colors. We don't want this to be an error, so pick + * off the first word, and try again. + */ + + if (Tcl_SplitList(interp, string, &argc, &argv) == TCL_OK ) { + if (argc > 1) { + FindCursorByName(macCursorPtr, argv[0]); + } + ckfree((char *) argv); + } + } } if (macCursorPtr->macCursor == NULL) { - ckfree((char *)macCursorPtr); - Tcl_AppendResult(interp, "bad cursor spec \"", string, "\"", - (char *) NULL); - return NULL; + ckfree((char *)macCursorPtr); + Tcl_AppendResult(interp, "bad cursor spec \"", string, "\"", NULL); + return NULL; } else { - return (TkCursor *) macCursorPtr; + return (TkCursor *) macCursorPtr; } } @@ -272,26 +279,26 @@ TkGetCursorByName( * * TkCreateCursorFromData -- * - * Creates a cursor from the source and mask bits. + * Creates a cursor from the source and mask bits. * * Results: - * Returns a new cursor, or NULL on errors. + * Returns a new cursor, or NULL on errors. * * Side effects: - * Allocates a new cursor. + * Allocates a new cursor. * *---------------------------------------------------------------------- */ TkCursor * TkCreateCursorFromData( - Tk_Window tkwin, /* Window in which cursor will be used. */ - CONST char *source, /* Bitmap data for cursor shape. */ - CONST char *mask, /* Bitmap data for cursor mask. */ - int width, int height, /* Dimensions of cursor. */ - int xHot, int yHot, /* Location of hot-spot in cursor. */ - XColor fgColor, /* Foreground color for cursor. */ - XColor bgColor) /* Background color for cursor. */ + Tk_Window tkwin, /* Window in which cursor will be used. */ + CONST char *source, /* Bitmap data for cursor shape. */ + CONST char *mask, /* Bitmap data for cursor mask. */ + int width, int height, /* Dimensions of cursor. */ + int xHot, int yHot, /* Location of hot-spot in cursor. */ + XColor fgColor, /* Foreground color for cursor. */ + XColor bgColor) /* Background color for cursor. */ { return NULL; } @@ -301,14 +308,14 @@ TkCreateCursorFromData( * * TkpFreeCursor -- * - * This procedure is called to release a cursor allocated by - * TkGetCursorByName. + * This procedure is called to release a cursor allocated by + * TkGetCursorByName. * * Results: - * None. + * None. * * Side effects: - * The cursor data structure is deallocated. + * The cursor data structure is deallocated. * *---------------------------------------------------------------------- */ @@ -320,32 +327,33 @@ TkpFreeCursor( TkMacOSXCursor *macCursorPtr = (TkMacOSXCursor *) cursorPtr; switch (macCursorPtr->type) { - case COLOR: - DisposeCCursor((CCrsrHandle) macCursorPtr->macCursor); - break; - case NORMAL: - ReleaseResource(macCursorPtr->macCursor); - break; + case COLOR: + DisposeCCursor((CCrsrHandle) macCursorPtr->macCursor); + break; + case NORMAL: + ReleaseResource(macCursorPtr->macCursor); + break; } if (macCursorPtr == gCurrentCursor) { - gCurrentCursor = NULL; + gCurrentCursor = NULL; } } + /* *---------------------------------------------------------------------- * * TkMacOSXInstallCursor -- * - * Installs either the current cursor as defined by TkpSetCursor - * or a resize cursor as the cursor the Macintosh should currently - * display. + * Installs either the current cursor as defined by TkpSetCursor + * or a resize cursor as the cursor the Macintosh should currently + * display. * * Results: - * None. + * None. * * Side effects: - * Changes the Macintosh mouse cursor. + * Changes the Macintosh mouse cursor. * *---------------------------------------------------------------------- */ @@ -358,45 +366,56 @@ TkMacOSXInstallCursor( CCrsrHandle ccursor; CursHandle cursor; static unsigned int cursorStep = 0; - + static int cursorHidden = 0; + int cursorNone = 0; + gResizeOverride = resizeOverride; if (resizeOverride) { - cursor = (CursHandle) GetNamedResource('CURS', "\presize"); - if (cursor) { - SetCursor(*cursor); - } else { -#ifdef TK_MAC_DEBUG - fprintf(stderr,"Resize cursor failed, %d\n", ResError()); -#endif - } + cursor = (CursHandle) GetNamedResource('CURS', "\presize"); + if (cursor) { + SetCursor(*cursor); + } else { + TkMacOSXDbgMsg("Resize cursor failed: %d", ResError()); + } } else if (macCursorPtr == NULL) { - SetThemeCursor(kThemeArrowCursor); + SetThemeCursor(kThemeArrowCursor); } else { - struct CursorName *namePtr; - switch (macCursorPtr->type) { - case THEME: - namePtr = (struct CursorName *) macCursorPtr->macCursor; - SetThemeCursor( - namePtr->id); - break; - case ANIMATED: - namePtr = (struct CursorName *) macCursorPtr->macCursor; - if (macCursorPtr->count == -1) { - SetAnimatedThemeCursor(namePtr->id, cursorStep++); - } else { - SetAnimatedThemeCursor(namePtr->id, macCursorPtr->count); - } - break; - case COLOR: - ccursor = (CCrsrHandle) macCursorPtr->macCursor; - SetCCursor(ccursor); - break; - case NORMAL: - cursor = (CursHandle) macCursorPtr->macCursor; - SetCursor(*cursor); - break; - } + struct CursorName *namePtr; + switch (macCursorPtr->type) { + case NONE: + if (!cursorHidden) { + cursorHidden = 1; + HideCursor(); + } + cursorNone = 1; + break; + case THEME: + namePtr = (struct CursorName *) macCursorPtr->macCursor; + SetThemeCursor( + namePtr->id); + break; + case ANIMATED: + namePtr = (struct CursorName *) macCursorPtr->macCursor; + if (macCursorPtr->count == -1) { + SetAnimatedThemeCursor(namePtr->id, cursorStep++); + } else { + SetAnimatedThemeCursor(namePtr->id, macCursorPtr->count); + } + break; + case COLOR: + ccursor = (CCrsrHandle) macCursorPtr->macCursor; + SetCCursor(ccursor); + break; + case NORMAL: + cursor = (CursHandle) macCursorPtr->macCursor; + SetCursor(*cursor); + break; + } + } + if (cursorHidden && !cursorNone) { + cursorHidden = 0; + ShowCursor(); } } @@ -405,13 +424,13 @@ TkMacOSXInstallCursor( * * TkpSetCursor -- * - * Set the current cursor and install it. + * Set the current cursor and install it. * * Results: - * None. + * None. * * Side effects: - * Changes the current cursor. + * Changes the current cursor. * *---------------------------------------------------------------------- */ @@ -421,30 +440,30 @@ TkpSetCursor( TkpCursor cursor) { int cursorChanged = 1; - + if (!gTkOwnsCursor) { - return; + return; } - + if (cursor == None) { - /* - * This is a little tricky. We can't really tell whether - * gCurrentCursor is NULL because it was NULL last time around - * or because we just freed the current cursor. So if the input - * cursor is NULL, we always need to reset it, we can't trust the - * cursorChanged logic. - */ - - gCurrentCursor = NULL; + /* + * This is a little tricky. We can't really tell whether + * gCurrentCursor is NULL because it was NULL last time around + * or because we just freed the current cursor. So if the input + * cursor is NULL, we always need to reset it, we can't trust the + * cursorChanged logic. + */ + + gCurrentCursor = NULL; } else { - if (gCurrentCursor == (TkMacOSXCursor *) cursor) { - cursorChanged = 0; - } - gCurrentCursor = (TkMacOSXCursor *) cursor; + if (gCurrentCursor == (TkMacOSXCursor *) cursor) { + cursorChanged = 0; + } + gCurrentCursor = (TkMacOSXCursor *) cursor; } if (Tk_MacOSXIsAppInFront() && cursorChanged) { - TkMacOSXInstallCursor(gResizeOverride); + TkMacOSXInstallCursor(gResizeOverride); } } @@ -453,13 +472,13 @@ TkpSetCursor( * * Tk_MacOSXTkOwnsCursor -- * - * Sets whether Tk has the right to adjust the cursor. + * Sets whether Tk has the right to adjust the cursor. * * Results: - * None. + * None. * * Side effects: - * May keep Tk from changing the cursor. + * May keep Tk from changing the cursor. * *---------------------------------------------------------------------- */ diff --git a/macosx/tkMacOSXCursors.r b/macosx/tkMacOSXCursors.r index 51abc74..248c8ba 100644 --- a/macosx/tkMacOSXCursors.r +++ b/macosx/tkMacOSXCursors.r @@ -1,21 +1,21 @@ -/* +/* * tkMacOSXCursors.r -- * * This file defines a set of Macintosh cursor resources that - * are only available on the Macintosh platform. + * are only available on the Macintosh platform. * * Copyright (c) 1995-1996 Sun Microsystems, Inc. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXCursors.r,v 1.2 2002/08/31 06:12:29 das Exp $ + * RCS: @(#) $Id: tkMacOSXCursors.r,v 1.3 2007/04/23 21:24:33 das Exp $ */ /* * These are resource definitions for Macintosh cursors. * The are identified and loaded by the "name" of the - * cursor. However, the ids must be unique. + * cursor. However, the ids must be unique. */ data 'CURS' (1000, "hand") { @@ -23,7 +23,7 @@ data 'CURS' (1000, "hand") { $"8802 4002 2002 2004 1004 0808 0408 0408" $"0180 1BF0 3FF8 3FFA 1FFF 1FFF 6FFF FFFF" $"FFFE 7FFE 3FFE 3FFC 1FFC 0FF8 07F8 07F8" - $"0009 0008" + $"0009 0008" }; data 'CURS' (1002, "bucket") { @@ -31,7 +31,7 @@ data 'CURS' (1002, "bucket") { $"129C 212C 104C 088C 050C 0208 0000 0000" $"0000 0000 0600 0980 09C0 0BF0 0FF8 0FFC" $"1FFC 3FEC 1FCC 0F8C 070C 0208 0000 0000" - $"000D 000C" + $"000D 000C" }; data 'CURS' (1003, "cancel") { @@ -39,7 +39,7 @@ data 'CURS' (1003, "cancel") { $"0A00 3F80 4A40 4A46 3186 0000 0000 0000" $"0000 0000 0000 3180 7BC0 FFE0 FFE0 7FC0" $"3F80 7FC0 FFE6 FFEF 7BCF 3186 0000 0000" - $"0008 0005" + $"0008 0005" }; data 'CURS' (1004, "resize") { @@ -47,7 +47,7 @@ data 'CURS' (1004, "resize") { $"9F8D 880D 880D 880D 8FFD 87FD 8001 FFFF" $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" $"FFFF FFFF FFFF FFFF FFFF FFFF FFFF FFFF" - $"0008 0008" + $"0008 0008" }; data 'CURS' (1005, "eyedrop") { @@ -55,7 +55,7 @@ data 'CURS' (1005, "eyedrop") { $"0440 0880 1100 2200 4400 4800 B000 4000" $"000E 001F 001F 00FF 007E 00F8 01F8 03E8" $"07C0 0F80 1F00 3E00 7C00 7800 F000 4000" - $"000F 0000" + $"000F 0000" }; data 'CURS' (1006, "eyedrop-full") { @@ -63,7 +63,7 @@ data 'CURS' (1006, "eyedrop-full") { $"07C0 0F80 1F00 3E00 7C00 7800 F000 4000" $"000E 001F 001F 00FF 007E 00F8 01F8 03E8" $"07C0 0F80 1F00 3E00 7C00 7800 F000 4000" - $"000F 0000" + $"000F 0000" }; data 'CURS' (1007, "zoom-in") { @@ -71,7 +71,7 @@ data 'CURS' (1007, "zoom-in") { $"A014 5028 5868 2798 187C 078E 0007 0003" $"0780 1FE0 3FF0 7878 7038 E01C EFDC EFDC" $"E01C 7038 7878 3FF8 1FFC 078E 0007 0003" - $"0007 0007" + $"0007 0007" }; data 'CURS' (1008, "zoom-out") { @@ -79,13 +79,13 @@ data 'CURS' (1008, "zoom-out") { $"A314 5328 5868 2798 187C 078E 0007 0003" $"0780 1FE0 3FF0 7878 7338 E31C EFDC EFDC" $"E31C 7338 7878 3FF8 1FFC 078E 0007 0003" - $"0007 0007" + $"0007 0007" }; /* * The following are resource definitions for color - * cursors on the Macintosh. If a color cursor and - * a black & white cursor are both defined with the + * cursors on the Macintosh. If a color cursor and + * a black & white cursor are both defined with the * same name preference will be given to the color * cursors. */ @@ -106,7 +106,7 @@ data 'crsr' (1000, "hand") { $"5570 0355 5570 00D5 55C0 0035 55C0 0035" $"55C0 0000 0000 0000 0002 0000 FFFF FFFF" $"FFFF 0001 FFFF CCCC 9999 0003 0000 0000" - $"0000" + $"0000" }; data 'crsr' (1001, "fist") { @@ -125,6 +125,6 @@ data 'crsr' (1001, "fist") { $"5570 0355 5570 00D5 55C0 0035 55C0 0035" $"55C0 0000 0000 0000 0002 0000 FFFF FFFF" $"FFFF 0001 FFFF CCCC 9999 0003 0000 0000" - $"0000" + $"0000" }; diff --git a/macosx/tkMacOSXDebug.c b/macosx/tkMacOSXDebug.c index 5537d1c..b0dc136 100644 --- a/macosx/tkMacOSXDebug.c +++ b/macosx/tkMacOSXDebug.c @@ -2,7 +2,7 @@ * tkMacOSXDebug.c -- * * Implementation of Macintosh specific functions for debugging MacOS events, - * regions, etc... + * regions, etc... * * Copyright 2001, Apple Computer, Inc. * Copyright (c) 2006-2007 Daniel A. Steffen @@ -10,51 +10,51 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * The following terms apply to all files originating from Apple - * Computer, Inc. ("Apple") and associated with the software - * unless explicitly disclaimed in individual files. + * The following terms apply to all files originating from Apple + * Computer, Inc. ("Apple") and associated with the software + * unless explicitly disclaimed in individual files. * * - * Apple hereby grants permission to use, copy, modify, - * distribute, and license this software and its documentation - * for any purpose, provided that existing copyright notices are - * retained in all copies and that this notice is included - * verbatim in any distributions. No written agreement, license, - * or royalty fee is required for any of the authorized - * uses. Modifications to this software may be copyrighted by - * their authors and need not follow the licensing terms - * described here, provided that the new terms are clearly - * indicated on the first page of each file where they apply. + * Apple hereby grants permission to use, copy, modify, + * distribute, and license this software and its documentation + * for any purpose, provided that existing copyright notices are + * retained in all copies and that this notice is included + * verbatim in any distributions. No written agreement, license, + * or royalty fee is required for any of the authorized + * uses. Modifications to this software may be copyrighted by + * their authors and need not follow the licensing terms + * described here, provided that the new terms are clearly + * indicated on the first page of each file where they apply. * * - * IN NO EVENT SHALL APPLE, THE AUTHORS OR DISTRIBUTORS OF THE - * SOFTWARE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, - * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF - * THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, - * EVEN IF APPLE OR THE AUTHORS HAVE BEEN ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. APPLE, THE AUTHORS AND - * DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS - * SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND APPLE,THE - * AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE - * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * IN NO EVENT SHALL APPLE, THE AUTHORS OR DISTRIBUTORS OF THE + * SOFTWARE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF + * THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, + * EVEN IF APPLE OR THE AUTHORS HAVE BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. APPLE, THE AUTHORS AND + * DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS + * SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND APPLE,THE + * AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE + * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * - * GOVERNMENT USE: If you are acquiring this software on behalf - * of the U.S. government, the Government shall have only - * "Restricted Rights" in the software and related documentation - * as defined in the Federal Acquisition Regulations (FARs) in - * Clause 52.227.19 (c) (2). If you are acquiring the software - * on behalf of the Department of Defense, the software shall be - * classified as "Commercial Computer Software" and the - * Government shall have only "Restricted Rights" as defined in - * Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the - * foregoing, the authors grant the U.S. Government and others - * acting in its behalf permission to use and distribute the - * software in accordance with the terms specified in this - * license. + * GOVERNMENT USE: If you are acquiring this software on behalf + * of the U.S. government, the Government shall have only + * "Restricted Rights" in the software and related documentation + * as defined in the Federal Acquisition Regulations (FARs) in + * Clause 52.227.19 (c) (2). If you are acquiring the software + * on behalf of the Department of Defense, the software shall be + * classified as "Commercial Computer Software" and the + * Government shall have only "Restricted Rights" as defined in + * Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the + * foregoing, the authors grant the U.S. Government and others + * acting in its behalf permission to use and distribute the + * software in accordance with the terms specified in this + * license. * - * RCS: @(#) $Id: tkMacOSXDebug.c,v 1.11 2007/03/07 23:46:34 das Exp $ + * RCS: @(#) $Id: tkMacOSXDebug.c,v 1.12 2007/04/23 21:24:33 das Exp $ */ #include "tkMacOSXInt.h" @@ -66,13 +66,13 @@ #include typedef struct { - EventKind kind; - char * name; + EventKind kind; + const char * name; } MyEventName; typedef struct { - EventClass c; - MyEventName * names; + EventClass c; + MyEventName * names; } MyEventNameList; static MyEventName windowEventNames [] = { @@ -161,7 +161,7 @@ static MyEventName keyboardEventNames [] = { static MyEventName appEventNames [] = { { kEventAppActivated, "Activated"}, - { kEventAppDeactivated, "Deactivated"}, + { kEventAppDeactivated, "Deactivated"}, { kEventAppQuit, "Quit"}, { kEventAppLaunchNotification, "LaunchNotification"}, { kEventAppLaunched, "Launched"}, @@ -253,83 +253,79 @@ static MyEventName classicEventNames [] = { }; #endif /* TK_MACOSXDEBUG_UNUSED */ -MODULE_SCOPE char * -TkMacOSXCarbonEventToAscii(EventRef eventRef, char * buf) -{ +MODULE_SCOPE char * +TkMacOSXCarbonEventToAscii(EventRef eventRef) +{ EventClass eventClass; - EventKind eventKind; + EventKind eventKind; MyEventNameList * list = eventNameList; - MyEventName * names = NULL; - int * iPtr = ( int * )buf; - char * iBuf = buf; + MyEventName * names = NULL; + static char str[256]; + char *buf = str; + int *iPtr = (int*)str; int found = 0; eventClass = GetEventClass(eventRef); eventKind = GetEventKind(eventRef); *iPtr = eventClass; - buf [ 4 ] = 0; + buf[4] = 0; strcat(buf, " "); buf += strlen(buf); while (list->names && (!names) ) { - if (eventClass == list->c) { - names = list -> names; - } else { - list++; - } + if (eventClass == list->c) { + names = list -> names; + } else { + list++; + } } - if (names) { - found = 0; - while (names->name && !found) { - if (eventKind == names->kind) { - sprintf(buf, "%-20s", names->name); - found = 1; - } else { - names++; - } - } - if (!found) { - sprintf(buf, "%-20d", eventKind ); - } - } else { - sprintf(buf, "%-20d", eventKind ); + while (names && names->name) { + if (eventKind == names->kind) { + snprintf(buf, 250, "%-20s", names->name); + break; + } else { + names++; + } + } + if (!found) { + snprintf(buf, 250, "%-20d", eventKind); } - return iBuf; + return str; } #ifdef TK_MACOSXDEBUG_UNUSED MODULE_SCOPE char * TkMacOSXCarbonEventKindToAscii(EventRef eventRef, char * buf ) -{ +{ EventClass eventClass; EventKind eventKind; MyEventNameList * list = eventNameList; - MyEventName * names = NULL; - int found = 0; + MyEventName * names = NULL; + int found = 0; eventClass = GetEventClass(eventRef); eventKind = GetEventKind(eventRef); while (list->names && (!names) ) { if (eventClass == list -> c) { - names = list -> names; + names = list -> names; } else { - list++; + list++; } } if (names) { found = 0; while ( names->name && !found ) { - if (eventKind == names->kind) { - sprintf(buf,"%s",names->name); - found = 1; - } else { - names++; - } + if (eventKind == names->kind) { + sprintf(buf,"%s",names->name); + found = 1; + } else { + names++; + } } } if (!found) { - sprintf ( buf,"%d", eventKind ); + sprintf ( buf,"%d", eventKind ); } else { - sprintf ( buf,"%d", eventKind ); + sprintf ( buf,"%d", eventKind ); } return buf; } @@ -337,46 +333,45 @@ TkMacOSXCarbonEventKindToAscii(EventRef eventRef, char * buf ) MODULE_SCOPE char * TkMacOSXClassicEventToAscii(EventRecord * eventPtr, char * buf ) { - MyEventName * names = NULL; + MyEventName * names = NULL; int found = 0; names = classicEventNames; while ( names -> name && !found ) - if (eventPtr->what == names->kind) { - int * iPtr; - char cBuf[8]; - iPtr=(int *) &cBuf; - *iPtr = eventPtr->message; - cBuf[4] = 0; - sprintf(buf, "%-16s %08x %04x %s", names->name, - (int) eventPtr->message, - eventPtr->modifiers, - cBuf); - found = 1; - } else { - names++; - } + if (eventPtr->what == names->kind) { + int * iPtr; + char cBuf[8]; + iPtr=(int *) &cBuf; + *iPtr = eventPtr->message; + cBuf[4] = 0; + sprintf(buf, "%-16s %08x %04x %s", names->name, + (int) eventPtr->message, + eventPtr->modifiers, + cBuf); + found = 1; + } else { + names++; + } if (!found) { - sprintf(buf,"%-16d %08x %08x, %s", - eventPtr->what, (int) eventPtr->message, - eventPtr->modifiers, buf); + sprintf(buf,"%-16d %08x %08x, %s", + eventPtr->what, (int) eventPtr->message, + eventPtr->modifiers, buf); } return buf; - + } MODULE_SCOPE void TkMacOSXPrintPoint(char * tag, Point * p ) { - fprintf(stderr,"%s %4d %4d\n", - tag,p->h,p->v ); + TkMacOSXDbgMsg("%s %4d %4d", tag,p->h,p->v ); } MODULE_SCOPE void TkMacOSXPrintRect(char * tag, Rect * r ) { - fprintf(stderr,"%s %4d %4d %4d %4d (%dx%d)\n", - tag, r->left, r->top, r->right, r->bottom, - r->right - r->left + 1, r->bottom - r->top + 1); + TkMacOSXDbgMsg("%s %4d %4d %4d %4d (%dx%d)", + tag, r->left, r->top, r->right, r->bottom, + r->right - r->left + 1, r->bottom - r->top + 1); } MODULE_SCOPE void @@ -393,23 +388,23 @@ TkMacOSXPrintWindowTitle(char * tag, WindowRef window ) Str255 title; GetWTitle(window,title); title [title[0] + 1] = 0; - fprintf(stderr, "%s %s\n", tag, title +1 ); + TkMacOSXDbgMsg("%s %s", tag, title +1 ); } typedef struct { - int msg; + int msg; char * name; } MsgName; static MsgName msgNames [] = { - { kMenuDrawMsg, "Draw"}, - { kMenuSizeMsg, "Size"}, - { kMenuPopUpMsg, "PopUp"}, - { kMenuCalcItemMsg, "CalcItem" }, + { kMenuDrawMsg, "Draw"}, + { kMenuSizeMsg, "Size"}, + { kMenuPopUpMsg, "PopUp"}, + { kMenuCalcItemMsg, "CalcItem" }, { kMenuThemeSavvyMsg, "ThemeSavvy"}, - { kMenuInitMsg, "Init" }, - { kMenuDisposeMsg, "Dispose" }, - { kMenuFindItemMsg, "FindItem" }, + { kMenuInitMsg, "Init" }, + { kMenuDisposeMsg, "Dispose" }, + { kMenuFindItemMsg, "FindItem" }, { kMenuHiliteItemMsg, "HiliteItem" }, { kMenuDrawItemsMsg, "DrawItems" }, { -1, NULL } @@ -420,12 +415,12 @@ TkMacOSXMenuMessageToAscii(int msg, char * s) { MsgName * msgNamePtr; for (msgNamePtr = msgNames;msgNamePtr->name;) { - if (msgNamePtr->msg == msg) { - strcpy(s,msgNamePtr->name); - return s; - } else { - msgNamePtr++; - } + if (msgNamePtr->msg == msg) { + strcpy(s,msgNamePtr->name); + return s; + } else { + msgNamePtr++; + } } sprintf(s,"unknown : %d", msg ); return s; @@ -434,24 +429,24 @@ TkMacOSXMenuMessageToAscii(int msg, char * s) static MsgName trackingNames [] = { { kMouseTrackingMousePressed , "MousePressed " }, { kMouseTrackingMouseReleased , "MouseReleased " }, - { kMouseTrackingMouseExited , "MouseExited " }, + { kMouseTrackingMouseExited , "MouseExited " }, { kMouseTrackingMouseEntered , "MouseEntered " }, - { kMouseTrackingMouseMoved , "MouseMoved " }, + { kMouseTrackingMouseMoved , "MouseMoved " }, { kMouseTrackingKeyModifiersChanged, "KeyModifiersChanged" }, { kMouseTrackingUserCancelled , "UserCancelled " }, - { kMouseTrackingTimedOut , "TimedOut " }, + { kMouseTrackingTimedOut , "TimedOut " }, { -1, NULL } }; MODULE_SCOPE char * -TkMacOSXMouseTrackingResultToAscii(MouseTrackingResult r, char * buf) +TkMacOSXMouseTrackingResultToAscii(MouseTrackingResult r, char * buf) { MsgName * namePtr; for (namePtr = trackingNames; namePtr->name; namePtr++) { - if (namePtr->msg == r) { - strcpy(buf, namePtr->name); - return buf; - } + if (namePtr->msg == r) { + strcpy(buf, namePtr->name); + return buf; + } } sprintf(buf, "Unknown mouse tracking result : %d", r); return buf; @@ -464,24 +459,24 @@ TkMacOSXMouseTrackingResultToAscii(MouseTrackingResult r, char * buf) * TkMacOSXGetNamedDebugSymbol -- * * - * Dynamically acquire address of a named symbol from a loaded - * dynamic library, so that we can use API that may not be - * available on all OS versions. - * For debugging purposes, if we cannot find the symbol with the - * usual dynamic library APIs, we manually walk the symbol table - * of the loaded library. This allows access to unexported - * symbols such as private_extern internal debugging functions. - * If module is NULL or the empty string, search all loaded - * libraries (could be very expensive and should be avoided). + * Dynamically acquire address of a named symbol from a loaded + * dynamic library, so that we can use API that may not be + * available on all OS versions. + * For debugging purposes, if we cannot find the symbol with the + * usual dynamic library APIs, we manually walk the symbol table + * of the loaded library. This allows access to unexported + * symbols such as private_extern internal debugging functions. + * If module is NULL or the empty string, search all loaded + * libraries (could be very expensive and should be avoided). + * + * THIS FUCTION IS ONLY TO BE USED FOR DEBUGGING PURPOSES, IT MAY + * BREAK UNEXPECTEDLY IN THE FUTURE ! * - * THIS FUCTION IS ONLY TO BE USED FOR DEBUGGING PURPOSES, IT MAY - * BREAK UNEXPECTEDLY IN THE FUTURE ! - * * Results: - * Address of given symbol or NULL if unavailable. + * Address of given symbol or NULL if unavailable. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ @@ -519,8 +514,8 @@ TkMacOSXGetNamedDebugSymbol(const char* module, const char* symbol) struct symtab_command *st = NULL; struct segment_command *sg = NULL; uint32_t j, m, nsect = 0, txtsectx = 0; - - lc = (struct load_command*)((char *) mh + + + lc = (struct load_command*)((const char*) mh + sizeof(struct mach_header)); m = mh->ncmds; for (j = 0; j < m; j++) { @@ -531,12 +526,12 @@ TkMacOSXGetNamedDebugSymbol(const char* module, const char* symbol) if (!txtsectx) { /* Count total sections until (__TEXT, __text) */ uint32_t k, ns = sg->nsects; - + if (strcmp(sg->segname, SEG_TEXT) == 0) { struct section *s = (struct section *)( (char *)sg + sizeof(struct segment_command)); - + for(k = 0; k < ns; k++) { if (strcmp(s->sectname, SECT_TEXT) == 0) { txtsectx = nsect+k+1; @@ -559,7 +554,7 @@ TkMacOSXGetNamedDebugSymbol(const char* module, const char* symbol) struct nlist *sym; uint32_t strsize = st->strsize; int32_t strx; - + /* Offset file positions by difference to actual position in memory of last segment before symbol table: */ base = (intptr_t) sg->vmaddr + slide - sg->fileoff; @@ -573,7 +568,7 @@ TkMacOSXGetNamedDebugSymbol(const char* module, const char* symbol) sym->n_sect == txtsectx && strx > 0 && (uint32_t) strx < strsize && strcmp(strings + strx, symbol) == 0) { - addr = (void*) sym->n_value + slide; + addr = (char*) sym->n_value + slide; break; } sym++; diff --git a/macosx/tkMacOSXDebug.h b/macosx/tkMacOSXDebug.h index 9531ac8..235060d 100644 --- a/macosx/tkMacOSXDebug.h +++ b/macosx/tkMacOSXDebug.h @@ -2,55 +2,59 @@ * tkMacOSXDebug.h -- * * Declarations of Macintosh specific functions for debugging MacOS events, - * regions, etc... + * regions, etc... * - * Copyright 2001, Apple Computer, Inc. + * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2005-2007 Daniel A. Steffen * - * The following terms apply to all files originating from Apple - * Computer, Inc. ("Apple") and associated with the software - * unless explicitly disclaimed in individual files. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. * + * The following terms apply to all files originating from Apple + * Computer, Inc. ("Apple") and associated with the software + * unless explicitly disclaimed in individual files. * - * Apple hereby grants permission to use, copy, modify, - * distribute, and license this software and its documentation - * for any purpose, provided that existing copyright notices are - * retained in all copies and that this notice is included - * verbatim in any distributions. No written agreement, license, - * or royalty fee is required for any of the authorized - * uses. Modifications to this software may be copyrighted by - * their authors and need not follow the licensing terms - * described here, provided that the new terms are clearly - * indicated on the first page of each file where they apply. * + * Apple hereby grants permission to use, copy, modify, + * distribute, and license this software and its documentation + * for any purpose, provided that existing copyright notices are + * retained in all copies and that this notice is included + * verbatim in any distributions. No written agreement, license, + * or royalty fee is required for any of the authorized + * uses. Modifications to this software may be copyrighted by + * their authors and need not follow the licensing terms + * described here, provided that the new terms are clearly + * indicated on the first page of each file where they apply. * - * IN NO EVENT SHALL APPLE, THE AUTHORS OR DISTRIBUTORS OF THE - * SOFTWARE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, - * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF - * THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, - * EVEN IF APPLE OR THE AUTHORS HAVE BEEN ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. APPLE, THE AUTHORS AND - * DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS - * SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND APPLE,THE - * AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE - * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * - * GOVERNMENT USE: If you are acquiring this software on behalf - * of the U.S. government, the Government shall have only - * "Restricted Rights" in the software and related documentation - * as defined in the Federal Acquisition Regulations (FARs) in - * Clause 52.227.19 (c) (2). If you are acquiring the software - * on behalf of the Department of Defense, the software shall be - * classified as "Commercial Computer Software" and the - * Government shall have only "Restricted Rights" as defined in - * Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the - * foregoing, the authors grant the U.S. Government and others - * acting in its behalf permission to use and distribute the - * software in accordance with the terms specified in this - * license. + * IN NO EVENT SHALL APPLE, THE AUTHORS OR DISTRIBUTORS OF THE + * SOFTWARE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF + * THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, + * EVEN IF APPLE OR THE AUTHORS HAVE BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. APPLE, THE AUTHORS AND + * DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS + * SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND APPLE,THE + * AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE + * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * - * RCS: @(#) $Id: tkMacOSXDebug.h,v 1.9 2006/10/31 22:33:34 das Exp $ + * GOVERNMENT USE: If you are acquiring this software on behalf + * of the U.S. government, the Government shall have only + * "Restricted Rights" in the software and related documentation + * as defined in the Federal Acquisition Regulations (FARs) in + * Clause 52.227.19 (c) (2). If you are acquiring the software + * on behalf of the Department of Defense, the software shall be + * classified as "Commercial Computer Software" and the + * Government shall have only "Restricted Rights" as defined in + * Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the + * foregoing, the authors grant the U.S. Government and others + * acting in its behalf permission to use and distribute the + * software in accordance with the terms specified in this + * license. + * + * RCS: @(#) $Id: tkMacOSXDebug.h,v 1.10 2007/04/23 21:24:33 das Exp $ */ #ifndef _TKMACDEBUG @@ -60,12 +64,9 @@ #include "tkMacOSXInt.h" #endif -/* The following define enables printing of debug messages to stderr: */ -/* #define TK_MAC_DEBUG 1 */ - #ifdef TK_MAC_DEBUG -MODULE_SCOPE char* TkMacOSXCarbonEventToAscii(EventRef eventRef, char * buf ); +MODULE_SCOPE char* TkMacOSXCarbonEventToAscii(EventRef eventRef); #ifdef TK_MACOSXDEBUG_UNUSED MODULE_SCOPE char* TkMacOSXCarbonEventKindToAscii(EventRef eventRef, char * buf ); @@ -87,7 +88,7 @@ MODULE_SCOPE void* TkMacOSXGetNamedDebugSymbol(const char* module, const char* s #define TkMacOSXInitNamedDebugSymbol(module, ret, symbol, ...) \ static ret (* symbol)(__VA_ARGS__) = (void*)(-1L); \ if (symbol == (void*)(-1L)) { \ - symbol = TkMacOSXGetNamedDebugSymbol(STRINGIFY(module), STRINGIFY(_##symbol));\ + symbol = TkMacOSXGetNamedDebugSymbol(STRINGIFY(module), STRINGIFY(_##symbol));\ } #endif /* TK_MAC_DEBUG */ diff --git a/macosx/tkMacOSXDefault.h b/macosx/tkMacOSXDefault.h index 54f5f66..0a997ec 100644 --- a/macosx/tkMacOSXDefault.h +++ b/macosx/tkMacOSXDefault.h @@ -7,11 +7,12 @@ * Copyright (c) 1991-1994 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2006-2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXDefault.h,v 1.11 2006/09/10 17:06:32 das Exp $ + * RCS: @(#) $Id: tkMacOSXDefault.h,v 1.12 2007/04/23 21:24:33 das Exp $ */ #ifndef _TKMACDEFAULT @@ -28,17 +29,16 @@ * DISABLED - Foreground color when widget is disabled. */ -#define BLACK "Black" -#define WHITE "White" - -#define NORMAL_BG "systemWindowBody" -#define ACTIVE_BG "#ececec" -#define SELECT_BG "systemHighlight" -#define SELECT_FG "systemHighlightText" -#define INACTIVE_SELECT_BG "systemHighlightSecondary" -#define TROUGH "#c3c3c3" -#define INDICATOR "#b03060" -#define DISABLED "#a3a3a3" +#define BLACK "Black" +#define WHITE "White" +#define NORMAL_BG "systemWindowBody" +#define ACTIVE_BG "#ececec" +#define SELECT_BG "systemHighlight" +#define SELECT_FG None +#define INACTIVE_SELECT_BG "systemHighlightSecondary" +#define TROUGH "#c3c3c3" +#define INDICATOR "#b03060" +#define DISABLED "#a3a3a3" /* * Defaults for labels, buttons, checkbuttons, and radiobuttons: @@ -50,7 +50,7 @@ #define DEF_BUTTON_ACTIVE_FG_COLOR "systemButtonFace" #define DEF_CHKRAD_ACTIVE_FG_COLOR DEF_BUTTON_ACTIVE_FG_COLOR #define DEF_BUTTON_ACTIVE_FG_MONO WHITE -//IGR#define DEF_BUTTON_BG_COLOR "systemButtonFace" +/* #define DEF_BUTTON_BG_COLOR "systemButtonFace"*/ #define DEF_BUTTON_BG_COLOR WHITE #define DEF_BUTTON_BG_MONO WHITE #define DEF_BUTTON_BITMAP "" @@ -61,8 +61,7 @@ #define DEF_BUTTON_DEFAULT "disabled" #define DEF_BUTTON_DISABLED_FG_COLOR DISABLED #define DEF_BUTTON_DISABLED_FG_MONO "" -//IGR#define DEF_BUTTON_FG "systemButtonText" -#define DEF_BUTTON_FG BLACK +#define DEF_BUTTON_FG "systemButtonText" #define DEF_CHKRAD_FG DEF_BUTTON_FG #define DEF_BUTTON_FONT "system" #define DEF_BUTTON_HEIGHT "0" @@ -127,7 +126,7 @@ #define DEF_CANVAS_SELECT_MONO BLACK #define DEF_CANVAS_SELECT_BD_COLOR "1" #define DEF_CANVAS_SELECT_BD_MONO "0" -#define DEF_CANVAS_SELECT_FG_COLOR BLACK +#define DEF_CANVAS_SELECT_FG_COLOR SELECT_FG #define DEF_CANVAS_SELECT_FG_MONO WHITE #define DEF_CANVAS_TAKE_FOCUS (char *) NULL #define DEF_CANVAS_WIDTH "10c" @@ -139,14 +138,14 @@ /* * Defaults for entries: */ - -/* + +/* * I test the following two values in TkpDrawEntryBorderAndFocus - * to determine whether to use the native entry widget. So if + * to determine whether to use the native entry widget. So if * you change the defaults to be different from these, then you * won't get the native widget by default. */ - + #define MAC_OSX_FOCUS_WIDTH 3 #define MAC_OSX_ENTRY_BORDER 2 #define MAC_OSX_ENTRY_RELIEF TK_RELIEF_SUNKEN @@ -289,29 +288,29 @@ * Defaults for menus overall: */ -#define DEF_MENU_ACTIVE_BG_COLOR "SystemMenuActive" +#define DEF_MENU_ACTIVE_BG_COLOR "systemMenuActive" #define DEF_MENU_ACTIVE_BG_MONO BLACK #define DEF_MENU_ACTIVE_BORDER_WIDTH "0" -#define DEF_MENU_ACTIVE_FG_COLOR "SystemMenuActiveText" +#define DEF_MENU_ACTIVE_FG_COLOR "systemMenuActiveText" #define DEF_MENU_ACTIVE_FG_MONO WHITE -#define DEF_MENU_BG_COLOR "SystemMenu" +#define DEF_MENU_BG_COLOR "systemMenu" #define DEF_MENU_BG_MONO WHITE #define DEF_MENU_BORDER_WIDTH "0" #define DEF_MENU_CURSOR "arrow" -#define DEF_MENU_DISABLED_FG_COLOR "SystemMenuDisabled" +#define DEF_MENU_DISABLED_FG_COLOR "systemMenuDisabled" #define DEF_MENU_DISABLED_FG_MONO "" -#define DEF_MENU_FONT "system" -#define DEF_MENU_FG "SystemMenuText" +#define DEF_MENU_FONT "menu" +#define DEF_MENU_FG "systemMenuText" #define DEF_MENU_POST_COMMAND "" #define DEF_MENU_RELIEF "flat" -#define DEF_MENU_SELECT_COLOR "SystemMenuActive" +#define DEF_MENU_SELECT_COLOR "systemMenuActive" #define DEF_MENU_SELECT_MONO BLACK #define DEF_MENU_TAKE_FOCUS "0" /* * FIXME: Turn the default back to 1 when we make tearoff menus work again. */ - + #define DEF_MENU_TEAROFF "0" #define DEF_MENU_TEAROFF_CMD (char *) NULL #define DEF_MENU_TITLE "" @@ -334,7 +333,7 @@ #define DEF_MENUBUTTON_DIRECTION "below" #define DEF_MENUBUTTON_DISABLED_FG_COLOR DISABLED #define DEF_MENUBUTTON_DISABLED_FG_MONO "" -#define DEF_MENUBUTTON_FONT "system" +#define DEF_MENUBUTTON_FONT "menu" #define DEF_MENUBUTTON_FG BLACK #define DEF_MENUBUTTON_HEIGHT "0" #define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR @@ -483,8 +482,7 @@ #define DEF_SCROLLBAR_TAKE_FOCUS (char *) NULL #define DEF_SCROLLBAR_TROUGH_COLOR TROUGH #define DEF_SCROLLBAR_TROUGH_MONO WHITE -/*#define DEF_SCROLLBAR_WIDTH "15" */ -#define DEF_SCROLLBAR_WIDTH "16" +#define DEF_SCROLLBAR_WIDTH "15" /* * Defaults for texts: @@ -509,7 +507,7 @@ #define DEF_TEXT_INSERT_OFF_TIME "300" #define DEF_TEXT_INSERT_ON_TIME "600" #define DEF_TEXT_INSERT_WIDTH "1" -#define DEF_TEXT_MAX_UNDO "0" +#define DEF_TEXT_MAX_UNDO "0" #define DEF_TEXT_PADX "1" #define DEF_TEXT_PADY "1" #define DEF_TEXT_RELIEF "flat" @@ -529,7 +527,7 @@ #define DEF_TEXT_TABS "" #define DEF_TEXT_TABSTYLE "tabular" #define DEF_TEXT_TAKE_FOCUS (char *) NULL -#define DEF_TEXT_UNDO "0" +#define DEF_TEXT_UNDO "0" #define DEF_TEXT_WIDTH "80" #define DEF_TEXT_WRAP "char" #define DEF_TEXT_XSCROLL_COMMAND "" diff --git a/macosx/tkMacOSXDialog.c b/macosx/tkMacOSXDialog.c index 2db0ca5..114962b 100644 --- a/macosx/tkMacOSXDialog.c +++ b/macosx/tkMacOSXDialog.c @@ -1,15 +1,16 @@ /* * tkMacOSXDialog.c -- * - * Contains the Mac implementation of the common dialog boxes. + * Contains the Mac implementation of the common dialog boxes. * * Copyright (c) 1996-1997 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2006-2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXDialog.c,v 1.23 2007/04/21 19:06:37 hobbs Exp $ + * RCS: @(#) $Id: tkMacOSXDialog.c,v 1.24 2007/04/23 21:24:33 das Exp $ */ #include "tkMacOSXInt.h" @@ -22,28 +23,23 @@ #define StrBody(s) ((char *) (s) + 1) #endif -/* - * The following are ID's for resources that are defined in tkMacOSXResource.r - */ -#define OPEN_BOX 130 -#define OPEN_POPUP 131 -#define OPEN_MENU 132 #define OPEN_POPUP_ITEM 10 -#define SAVE_FILE 0 -#define OPEN_FILE 1 -#define CHOOSE_FOLDER 2 +#define SAVE_FILE 0 +#define OPEN_FILE 1 +#define CHOOSE_FOLDER 2 -#define MATCHED 0 -#define UNMATCHED 1 +#define MATCHED 0 +#define UNMATCHED 1 #define TK_DEFAULT_ABOUT 128 /* - * The following structure is used in the GetFileName() function. It stored + * The following structures are used in the GetFileName() function. They store * information about the file dialog and the file filters. */ -typedef struct _OpenFileData { + +typedef struct OpenFileData { FileFilterList fl; /* List of file filters. */ SInt16 curType; /* The filetype currently being listed. */ short popupItem; /* Item number of the popup in the dialog. */ @@ -52,37 +48,47 @@ typedef struct _OpenFileData { * option is set). */ } OpenFileData; +typedef struct NavHandlerUserData { + OpenFileData *ofdPtr; + NavReplyRecord reply; + OSStatus err; + CFStringRef saveNameRef; + int sheet; + WindowRef dialogWindow, origUnavailWindow; + WindowModality origModality; +} NavHandlerUserData; /* - * The following structure is used in the tk_messageBox - * implementation. + * The following structure is used in the tk_messageBox implementation. */ + typedef struct { - WindowRef windowRef; - int buttonIndex; -} CallbackUserData; + int buttonIndex; + WindowRef dialogWindow, origUnavailWindow; + WindowModality origModality; + EventHandlerRef handlerRef; +} AlertHandlerUserData; static OSStatus AlertHandler(EventHandlerCallRef callRef, EventRef eventRef, void *userData); -static Boolean MatchOneType(StringPtr fileNamePtr, OSType fileType, +static Boolean MatchOneType(StringPtr fileNamePtr, OSType fileType, OpenFileData *myofdPtr, FileFilter *filterPtr); -static pascal Boolean OpenFileFilterProc(AEDesc* theItem, void* info, +static pascal Boolean OpenFileFilterProc(AEDesc* theItem, void* info, NavCallBackUserData callBackUD, NavFilterModes filterMode); -static pascal void OpenEventProc(NavEventCallbackMessage callBackSelector, +static pascal void OpenEventProc(NavEventCallbackMessage callBackSelector, NavCBRecPtr callBackParms, NavCallBackUserData callBackUD); -static void InitFileDialogs(); -static int NavServicesGetFile(Tcl_Interp *interp, OpenFileData *ofd, - AEDesc *initialDescPtr, +static void InitFileDialogs(void); +static int NavServicesGetFile(Tcl_Interp *interp, + OpenFileData *ofd, AEDesc *initialDescPtr, char *initialFile, AEDescList *selectDescPtr, - CFStringRef title, CFStringRef message, int multiple, int isOpen); -static int HandleInitialDirectory (Tcl_Interp *interp, - char *initialFile, char *initialDir, - FSRef *dirRef, - AEDescList *selectDescPtr, - AEDesc *dirDescPtr); + CFStringRef title, CFStringRef message, + int multiple, int isOpen, Tk_Window parent); +static int HandleInitialDirectory(Tcl_Interp *interp, + char *initialFile, char *initialDir, FSRef *dirRef, + AEDescList *selectDescPtr, AEDesc *dirDescPtr); /* * Have we initialized the file dialog subsystem @@ -104,87 +110,87 @@ static NavEventUPP openFileEventUPP; * * Tk_ChooseColorObjCmd -- * - * This procedure implements the color dialog box for the Mac - * platform. See the user documentation for details on what it - * does. + * This procedure implements the color dialog box for the Mac + * platform. See the user documentation for details on what it + * does. * * Results: - * A standard Tcl result. + * A standard Tcl result. * * Side effects: - * See the user documentation. + * See the user documentation. * *---------------------------------------------------------------------- */ int Tk_ChooseColorObjCmd( - ClientData clientData, /* Main window associated with interpreter. */ - Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ - Tcl_Obj *CONST objv[]) /* Argument objects. */ + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { - Tk_Window parent; - char *title; - int i, picked, srcRead, dstWrote; - ColorPickerInfo cpinfo; + OSStatus err; + Tk_Window parent, tkwin = (Tk_Window) clientData; + const char *title; + int i, picked = 0, srcRead, dstWrote; + CMError cmerr; + CMProfileRef prof; + NColorPickerInfo cpinfo; static int inited = 0; static RGBColor in; - static CONST char *optionStrings[] = { - "-initialcolor", "-parent", "-title", NULL + static const char *optionStrings[] = { + "-initialcolor", "-parent", "-title", NULL }; enum options { - COLOR_INITIAL, COLOR_PARENT, COLOR_TITLE + COLOR_INITIAL, COLOR_PARENT, COLOR_TITLE }; if (inited == 0) { - /* - * 'in' stores the last color picked. The next time the color dialog - * pops up, the last color will remain in the dialog. - */ + /* + * 'in' stores the last color picked. The next time the color + * dialog pops up, the last color will remain in the dialog. + */ in.red = 0xffff; in.green = 0xffff; in.blue = 0xffff; inited = 1; } - - parent = (Tk_Window) clientData; title = "Choose a color:"; - picked = 0; for (i = 1; i < objc; i += 2) { - int index; - char *option, *value; + int index; + const char *option, *value; if (Tcl_GetIndexFromObj(interp, objv[i], optionStrings, "option", TCL_EXACT, &index) != TCL_OK) { return TCL_ERROR; } if (i + 1 == objc) { - option = Tcl_GetStringFromObj(objv[i], NULL); + option = Tcl_GetString(objv[i]); Tcl_AppendResult(interp, "value for \"", option, "\" missing", - (char *) NULL); + NULL); return TCL_ERROR; } - value = Tcl_GetStringFromObj(objv[i + 1], NULL); + value = Tcl_GetString(objv[i + 1]); switch ((enum options) index) { case COLOR_INITIAL: { XColor *colorPtr; - colorPtr = Tk_GetColor(interp, parent, value); + colorPtr = Tk_GetColor(interp, tkwin, value); if (colorPtr == NULL) { return TCL_ERROR; } - in.red = colorPtr->red; + in.red = colorPtr->red; in.green = colorPtr->green; - in.blue = colorPtr->blue; + in.blue = colorPtr->blue; Tk_FreeColor(colorPtr); break; } case COLOR_PARENT: { - parent = Tk_NameToWindow(interp, value, parent); + parent = Tk_NameToWindow(interp, value, tkwin); if (parent == NULL) { return TCL_ERROR; } @@ -197,31 +203,31 @@ Tk_ChooseColorObjCmd( } } - - cpinfo.theColor.profile = 0L; + cmerr = CMGetDefaultProfileBySpace(cmRGBData, &prof); + bzero(&cpinfo, sizeof(cpinfo)); + cpinfo.theColor.profile = prof; cpinfo.theColor.color.rgb.red = in.red; cpinfo.theColor.color.rgb.green = in.green; cpinfo.theColor.color.rgb.blue = in.blue; - cpinfo.dstProfile = 0L; - cpinfo.flags = kColorPickerCanModifyPalette - | kColorPickerCanAnimatePalette; - cpinfo.placeWhere = kDeepestColorScreen; - cpinfo.pickerType = 0L; - cpinfo.eventProc = NULL; - cpinfo.colorProc = NULL; - cpinfo.colorProcData = 0; - - /* This doesn't seem to actually set the title! */ - Tcl_UtfToExternal(NULL, NULL, title, -1, 0, NULL, + cpinfo.dstProfile = prof; + cpinfo.flags = kColorPickerDialogIsMoveable + | kColorPickerCanAnimatePalette; + cpinfo.placeWhere = kCenterOnMainScreen; + /* Currently, this does not actually change the colorpicker title */ + Tcl_UtfToExternal(NULL, TkMacOSXCarbonEncoding, title, -1, 0, NULL, StrBody(cpinfo.prompt), 255, &srcRead, &dstWrote, NULL); StrLength(cpinfo.prompt) = (unsigned char) dstWrote; - if ((PickColor(&cpinfo) == noErr) && (cpinfo.newColorChosen != 0)) { - in.red = cpinfo.theColor.color.rgb.red; - in.green = cpinfo.theColor.color.rgb.green; - in.blue = cpinfo.theColor.color.rgb.blue; + TkMacOSXTrackingLoop(1); + err = ChkErr(NPickColor, &cpinfo); + TkMacOSXTrackingLoop(0); + if ((err == noErr) && (cpinfo.newColorChosen != 0)) { + in.red = cpinfo.theColor.color.rgb.red; + in.green = cpinfo.theColor.color.rgb.green; + in.blue = cpinfo.theColor.color.rgb.blue; picked = 1; } + cmerr = CMCloseProfile(prof); if (picked != 0) { char result[32]; @@ -239,78 +245,65 @@ Tk_ChooseColorObjCmd( * * Tk_GetOpenFileObjCmd -- * - * This procedure implements the "open file" dialog box for the - * Mac platform. See the user documentation for details on what - * it does. + * This procedure implements the "open file" dialog box for the + * Mac platform. See the user documentation for details on what + * it does. * * Results: - * A standard Tcl result. + * A standard Tcl result. * * Side effects: - * See user documentation. + * See user documentation. *---------------------------------------------------------------------- */ int Tk_GetOpenFileObjCmd( - ClientData clientData, /* Main window associated with interpreter. */ - Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ - Tcl_Obj *CONST objv[]) /* Argument objects. */ + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { - int i, result, multiple; + int i, result = TCL_ERROR, multiple = 0; OpenFileData ofd; - Tk_Window parent; - CFStringRef message, title; + Tk_Window parent = NULL; + CFStringRef message = NULL, title = NULL; AEDesc initialDesc = {typeNull, NULL}; FSRef dirRef; AEDesc *initialPtr = NULL; AEDescList selectDesc = {typeNull, NULL}; char *initialFile = NULL, *initialDir = NULL; - static CONST char *openOptionStrings[] = { - "-defaultextension", "-filetypes", - "-initialdir", "-initialfile", - "-message", "-multiple", - "-parent", "-title", NULL + static const char *openOptionStrings[] = { + "-defaultextension", "-filetypes", "-initialdir", "-initialfile", + "-message", "-multiple", "-parent", "-title", NULL }; enum openOptions { - OPEN_DEFAULT, OPEN_FILETYPES, - OPEN_INITDIR, OPEN_INITFILE, - OPEN_MESSAGE, OPEN_MULTIPLE, - OPEN_PARENT, OPEN_TITLE + OPEN_DEFAULT, OPEN_FILETYPES, OPEN_INITDIR, OPEN_INITFILE, + OPEN_MESSAGE, OPEN_MULTIPLE, OPEN_PARENT, OPEN_TITLE }; if (!fileDlgInited) { InitFileDialogs(); } - - result = TCL_ERROR; - parent = (Tk_Window) clientData; - multiple = false; - title = NULL; - message = NULL; - TkInitFileFilters(&ofd.fl); - - ofd.curType = 0; - ofd.popupItem = OPEN_POPUP_ITEM; - ofd.usePopup = 1; + ofd.curType = 0; + ofd.popupItem = OPEN_POPUP_ITEM; + ofd.usePopup = 1; for (i = 1; i < objc; i += 2) { char *choice; int index, choiceLen; char *string; + Tcl_Obj *types; if (Tcl_GetIndexFromObj(interp, objv[i], openOptionStrings, "option", TCL_EXACT, &index) != TCL_OK) { - result = TCL_ERROR; goto end; } if (i + 1 == objc) { - string = Tcl_GetStringFromObj(objv[i], NULL); + string = Tcl_GetString(objv[i]); Tcl_AppendResult(interp, "value for \"", string, "\" missing", - (char *) NULL); - result = TCL_ERROR; + NULL); goto end; } @@ -318,9 +311,8 @@ Tk_GetOpenFileObjCmd( case OPEN_DEFAULT: break; case OPEN_FILETYPES: - if (TkGetFileFilters(interp, &ofd.fl, objv[i + 1], 0) - != TCL_OK) { - result = TCL_ERROR; + types = objv[i + 1]; + if (TkGetFileFilters(interp, &ofd.fl, types, 0) != TCL_OK) { goto end; } break; @@ -330,61 +322,61 @@ Tk_GetOpenFileObjCmd( if (choiceLen == 0) { initialDir = NULL; } break; case OPEN_INITFILE: - initialFile = Tcl_GetStringFromObj(objv[i + 1], NULL); + initialFile = Tcl_GetString(objv[i + 1]); /* empty strings should be like no selection given */ if (choiceLen == 0) { initialFile = NULL; } break; case OPEN_MESSAGE: choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); - message = CFStringCreateWithBytes(NULL, (unsigned char*) choice, choiceLen, - kCFStringEncodingUTF8, false); + message = CFStringCreateWithBytes(NULL, (unsigned char*) + choice, choiceLen, kCFStringEncodingUTF8, false); break; case OPEN_MULTIPLE: if (Tcl_GetBooleanFromObj(interp, objv[i + 1], &multiple) != TCL_OK) { - result = TCL_ERROR; goto end; } break; case OPEN_PARENT: choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); - parent = Tk_NameToWindow(interp, choice, parent); + parent = Tk_NameToWindow(interp, choice, + (Tk_Window) clientData); if (parent == NULL) { - result = TCL_ERROR; goto end; } break; case OPEN_TITLE: choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); - title = CFStringCreateWithBytes(NULL, (unsigned char*) choice, choiceLen, - kCFStringEncodingUTF8, false); + title = CFStringCreateWithBytes(NULL, (unsigned char*) + choice, choiceLen, kCFStringEncodingUTF8, false); break; } } if (HandleInitialDirectory(interp, initialFile, initialDir, &dirRef, - &selectDesc, &initialDesc) != TCL_OK) { - result = TCL_ERROR; + &selectDesc, &initialDesc) != TCL_OK) { goto end; } if (initialDesc.descriptorType == typeFSRef) { initialPtr = &initialDesc; } - result = NavServicesGetFile(interp, &ofd, initialPtr, - NULL, &selectDesc, title, message, multiple, OPEN_FILE); - - end: + result = NavServicesGetFile(interp, &ofd, initialPtr, NULL, &selectDesc, + title, message, multiple, OPEN_FILE, parent); +end: TkFreeFileFilters(&ofd.fl); - AEDisposeDesc(&initialDesc); - AEDisposeDesc(&selectDesc); - if (title != NULL) { + if (initialDesc.dataHandle) { + ChkErr(AEDisposeDesc, &initialDesc); + } + if (selectDesc.dataHandle) { + ChkErr(AEDisposeDesc, &selectDesc); + } + if (title) { CFRelease(title); } - if (message != NULL) { + if (message) { CFRelease(message); } - return result; } @@ -393,64 +385,58 @@ Tk_GetOpenFileObjCmd( * * Tk_GetSaveFileObjCmd -- * - * Same as Tk_GetOpenFileCmd but opens a "save file" dialog box - * instead + * Same as Tk_GetOpenFileCmd but opens a "save file" dialog box + * instead * * Results: - * A standard Tcl result. + * A standard Tcl result. * * Side effects: - * See user documentation. + * See user documentation. *---------------------------------------------------------------------- */ int Tk_GetSaveFileObjCmd( - ClientData clientData, /* Main window associated with interpreter. */ - Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ - Tcl_Obj *CONST objv[]) /* Argument objects. */ + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { - int i, result; + int i, result = TCL_ERROR; char *initialFile = NULL; - Tk_Window parent; + Tk_Window parent = NULL; AEDesc initialDesc = {typeNull, NULL}; AEDesc *initialPtr = NULL; FSRef dirRef; - CFStringRef title, message; + CFStringRef title = NULL, message = NULL; OpenFileData ofd; - static CONST char *saveOptionStrings[] = { - "-defaultextension", "-filetypes", "-initialdir", "-initialfile", - "-message", "-parent", "-title", NULL + static const char *saveOptionStrings[] = { + "-defaultextension", "-filetypes", "-initialdir", "-initialfile", + "-message", "-parent", "-title", NULL }; enum saveOptions { - SAVE_DEFAULT, SAVE_FILETYPES, SAVE_INITDIR, SAVE_INITFILE, - SAVE_MESSAGE, SAVE_PARENT, SAVE_TITLE + SAVE_DEFAULT, SAVE_FILETYPES, SAVE_INITDIR, SAVE_INITFILE, + SAVE_MESSAGE, SAVE_PARENT, SAVE_TITLE }; if (!fileDlgInited) { InitFileDialogs(); } - result = TCL_ERROR; - parent = (Tk_Window) clientData; - title = NULL; - message = NULL; - for (i = 1; i < objc; i += 2) { - char *choice; + char *choice, *string; int index, choiceLen; - char *string; if (Tcl_GetIndexFromObj(interp, objv[i], saveOptionStrings, "option", TCL_EXACT, &index) != TCL_OK) { - return TCL_ERROR; + goto end; } if (i + 1 == objc) { - string = Tcl_GetStringFromObj(objv[i], NULL); + string = Tcl_GetString(objv[i]); Tcl_AppendResult(interp, "value for \"", string, "\" missing", - (char *) NULL); - return TCL_ERROR; + NULL); + goto end; } switch (index) { case SAVE_DEFAULT: @@ -461,58 +447,57 @@ Tk_GetSaveFileObjCmd( case SAVE_INITDIR: choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); /* empty strings should be like no selection given */ - if (choiceLen && - HandleInitialDirectory(interp, NULL, choice, &dirRef, - NULL, &initialDesc) != TCL_OK) { - result = TCL_ERROR; + if (choiceLen && HandleInitialDirectory(interp, NULL, choice, + &dirRef, NULL, &initialDesc) != TCL_OK) { goto end; } break; case SAVE_INITFILE: initialFile = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); /* empty strings should be like no selection given */ - if (choiceLen == 0) { initialFile = NULL; } + if (choiceLen == 0) { + initialFile = NULL; + } break; case SAVE_MESSAGE: choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); - message = CFStringCreateWithBytes(NULL, (unsigned char*) choice, choiceLen, - kCFStringEncodingUTF8, false); + message = CFStringCreateWithBytes(NULL, (unsigned char*) + choice, choiceLen, kCFStringEncodingUTF8, false); break; case SAVE_PARENT: choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); - parent = Tk_NameToWindow(interp, choice, parent); + parent = Tk_NameToWindow(interp, choice, + (Tk_Window) clientData); if (parent == NULL) { - result = TCL_ERROR; goto end; } break; case SAVE_TITLE: choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); - title = CFStringCreateWithBytes(NULL, (unsigned char*) choice, choiceLen, - kCFStringEncodingUTF8, false); + title = CFStringCreateWithBytes(NULL, (unsigned char*) + choice, choiceLen, kCFStringEncodingUTF8, false); break; } } TkInitFileFilters(&ofd.fl); ofd.usePopup = 0; - if (initialDesc.descriptorType == typeFSRef) { initialPtr = &initialDesc; } result = NavServicesGetFile(interp, &ofd, initialPtr, initialFile, NULL, - title, message, false, SAVE_FILE); - - end: - - AEDisposeDesc(&initialDesc); - if (title != NULL) { + title, message, false, SAVE_FILE, parent); + TkFreeFileFilters(&ofd.fl); +end: + if (initialDesc.dataHandle) { + ChkErr(AEDisposeDesc, &initialDesc); + } + if (title) { CFRelease(title); } - if (message != NULL) { + if (message) { CFRelease(message); } - return result; } @@ -521,53 +506,43 @@ Tk_GetSaveFileObjCmd( * * Tk_ChooseDirectoryObjCmd -- * - * This procedure implements the "tk_chooseDirectory" dialog box - * for the Windows platform. See the user documentation for details - * on what it does. + * This procedure implements the "tk_chooseDirectory" dialog box + * for the Windows platform. See the user documentation for details + * on what it does. * * Results: - * See user documentation. + * See user documentation. * * Side effects: - * A modal dialog window is created. Tcl_SetServiceMode() is - * called to allow background events to be processed + * A modal dialog window is created. * *---------------------------------------------------------------------- */ int Tk_ChooseDirectoryObjCmd(clientData, interp, objc, objv) - ClientData clientData; /* Main window associated with interpreter. */ - Tcl_Interp *interp; /* Current interpreter. */ - int objc; /* Number of arguments. */ - Tcl_Obj *CONST objv[]; /* Argument objects. */ + ClientData clientData; /* Main window associated with interpreter. */ + Tcl_Interp *interp; /* Current interpreter. */ + int objc; /* Number of arguments. */ + Tcl_Obj *CONST objv[]; /* Argument objects. */ { - int i, result; - Tk_Window parent; - AEDesc initialDesc = {typeNull, NULL}; - AEDesc *initialPtr = NULL; + int i, result = TCL_ERROR; + Tk_Window parent = NULL; + AEDesc initialDesc = {typeNull, NULL}, *initialPtr = NULL; FSRef dirRef; - CFStringRef message, title; + CFStringRef message = NULL, title = NULL; OpenFileData ofd; - static CONST char *chooseOptionStrings[] = { + static const char *chooseOptionStrings[] = { "-initialdir", "-message", "-mustexist", "-parent", "-title", NULL }; enum chooseOptions { - CHOOSE_INITDIR, CHOOSE_MESSAGE, CHOOSE_MUSTEXIST, - CHOOSE_PARENT, CHOOSE_TITLE + CHOOSE_INITDIR, CHOOSE_MESSAGE, CHOOSE_MUSTEXIST, CHOOSE_PARENT, + CHOOSE_TITLE }; - if (!NavServicesAvailable()) { - return TCL_ERROR; - } - if (!fileDlgInited) { InitFileDialogs(); } - result = TCL_ERROR; - parent = (Tk_Window) clientData; - title = NULL; - message = NULL; for (i = 1; i < objc; i += 2) { char *choice; @@ -576,68 +551,82 @@ Tk_ChooseDirectoryObjCmd(clientData, interp, objc, objv) if (Tcl_GetIndexFromObj(interp, objv[i], chooseOptionStrings, "option", TCL_EXACT, &index) != TCL_OK) { - return TCL_ERROR; + goto end; } if (i + 1 == objc) { - string = Tcl_GetStringFromObj(objv[i], NULL); + string = Tcl_GetString(objv[i]); Tcl_AppendResult(interp, "value for \"", string, "\" missing", - (char *) NULL); - return TCL_ERROR; + NULL); + goto end; } switch (index) { case CHOOSE_INITDIR: choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); - if (choiceLen && - HandleInitialDirectory(interp, NULL, choice, &dirRef, - NULL, &initialDesc) != TCL_OK) { - result = TCL_ERROR; + if (choiceLen && HandleInitialDirectory(interp, NULL, choice, + &dirRef, NULL, &initialDesc) != TCL_OK) { goto end; } break; case CHOOSE_MESSAGE: choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); - message = CFStringCreateWithBytes(NULL, (unsigned char*) choice, choiceLen, - kCFStringEncodingUTF8, false); + message = CFStringCreateWithBytes(NULL, (unsigned char*) + choice, choiceLen, kCFStringEncodingUTF8, false); break; case CHOOSE_PARENT: choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); - parent = Tk_NameToWindow(interp, choice, parent); + parent = Tk_NameToWindow(interp, choice, + (Tk_Window) clientData); if (parent == NULL) { - result = TCL_ERROR; goto end; } break; case CHOOSE_TITLE: choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); - title = CFStringCreateWithBytes(NULL, (unsigned char*) choice, choiceLen, - kCFStringEncodingUTF8, false); + title = CFStringCreateWithBytes(NULL, (unsigned char*) choice, + choiceLen, kCFStringEncodingUTF8, false); break; } } TkInitFileFilters(&ofd.fl); ofd.usePopup = 0; - if (initialDesc.descriptorType == typeFSRef) { initialPtr = &initialDesc; } - result = NavServicesGetFile(interp, &ofd, initialPtr, NULL, NULL, - title, message, false, CHOOSE_FOLDER); - - end: - AEDisposeDesc(&initialDesc); - if (title != NULL) { + result = NavServicesGetFile(interp, &ofd, initialPtr, NULL, NULL, title, + message, false, CHOOSE_FOLDER, parent); + TkFreeFileFilters(&ofd.fl); +end: + if (initialDesc.dataHandle) { + ChkErr(AEDisposeDesc, &initialDesc); + } + if (title) { CFRelease(title); } - if (message != NULL) { + if (message) { CFRelease(message); } - return result; } + +/* + *---------------------------------------------------------------------- + * + * HandleInitialDirectory -- + * + * Helper for -initialdir setup. + * + * Results: + * Tcl result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ int -HandleInitialDirectory ( +HandleInitialDirectory( Tcl_Interp *interp, char *initialFile, char *initialDir, @@ -646,42 +635,37 @@ HandleInitialDirectory ( AEDesc *dirDescPtr) { Tcl_DString ds; - OSErr err; + OSStatus err; Boolean isDirectory; char *dirName = NULL; - int result = TCL_OK; + int result = TCL_ERROR; - if (initialDir != NULL) { + if (initialDir) { dirName = Tcl_TranslateFileName(interp, initialDir, &ds); if (dirName == NULL) { - return TCL_ERROR; + goto end; } - - err = FSPathMakeRef((unsigned char*) dirName, + err = ChkErr(FSPathMakeRef, (unsigned char*) dirName, dirRef, &isDirectory); - if (err != noErr) { - Tcl_AppendResult(interp, "bad directory \"", - initialDir, "\"", NULL); - result = TCL_ERROR; + Tcl_AppendResult(interp, "bad directory \"", initialDir, "\"", + NULL); goto end; } if (!isDirectory) { Tcl_AppendResult(interp, "-intialdir \"", initialDir, " is a file, not a directory.\"", NULL); - result = TCL_ERROR; goto end; } - - AECreateDesc(typeFSRef, dirRef, sizeof(*dirRef), dirDescPtr); + ChkErr(AECreateDesc, typeFSRef, dirRef, sizeof(*dirRef), dirDescPtr); } - if (initialFile != NULL && selectDescPtr != NULL) { + if (initialFile && selectDescPtr) { FSRef fileRef; AEDesc fileDesc; char *namePtr; - if (initialDir != NULL) { + if (initialDir) { Tcl_DStringAppend(&ds, "/", 1); Tcl_DStringAppend(&ds, initialFile, -1); namePtr = Tcl_DStringValue(&ds); @@ -689,35 +673,68 @@ HandleInitialDirectory ( namePtr = initialFile; } - AECreateList(NULL, 0, false, selectDescPtr); + ChkErr(AECreateList, NULL, 0, false, selectDescPtr); - err = FSPathMakeRef((unsigned char*) namePtr, &fileRef, &isDirectory); + err = ChkErr(FSPathMakeRef, (unsigned char*) namePtr, &fileRef, + &isDirectory); if (err != noErr) { Tcl_AppendResult(interp, "bad initialfile \"", initialFile, "\" file does not exist.", NULL); - return TCL_ERROR; + goto end; } - AECreateDesc(typeFSRef, &fileRef, sizeof(fileRef), &fileDesc); - AEPutDesc(selectDescPtr, 1, &fileDesc); - AEDisposeDesc(&fileDesc); + ChkErr(AECreateDesc, typeFSRef, &fileRef, sizeof(fileRef), &fileDesc); + ChkErr(AEPutDesc, selectDescPtr, 1, &fileDesc); + ChkErr(AEDisposeDesc, &fileDesc); } - + result = TCL_OK; end: - if (dirName != NULL) { + if (dirName) { Tcl_DStringFree(&ds); } return result; } + +/* + *---------------------------------------------------------------------- + * + * InitFileDialogs -- + * + * Initialize file dialog subsystem. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ -static void -InitFileDialogs() +void +InitFileDialogs(void) { fileDlgInited = 1; openFileFilterUPP = NewNavObjectFilterUPP(OpenFileFilterProc); openFileEventUPP = NewNavEventUPP(OpenEventProc); } + +/* + *---------------------------------------------------------------------- + * + * NavServicesGetFile -- + * + * Common wrapper for NavServices API. + * + * Results: + * Tcl result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ -static int +int NavServicesGetFile( Tcl_Interp *interp, OpenFileData *ofdPtr, @@ -727,30 +744,43 @@ NavServicesGetFile( CFStringRef title, CFStringRef message, int multiple, - int isOpen) + int isOpen, + Tk_Window parent) { - NavReplyRecord theReply; - NavDialogCreationOptions diagOptions; + NavHandlerUserData data; + NavDialogCreationOptions options; NavDialogRef dialogRef = NULL; CFStringRef * menuItemNames = NULL; - OSErr err; + OSStatus err; Tcl_Obj *theResult = NULL; - int result; + int result = TCL_ERROR; - err = NavGetDefaultDialogCreationOptions(&diagOptions); - if (err!=noErr) { - return TCL_ERROR; + bzero(&data, sizeof(data)); + err = NavGetDefaultDialogCreationOptions(&options); + if (err != noErr) { + return result; } - diagOptions.location.h = -1; - diagOptions.location.v = -1; - diagOptions.optionFlags = kNavDontAutoTranslate - + kNavDontAddTranslateItems; + options.optionFlags = kNavDontAutoTranslate | kNavDontAddTranslateItems + | kNavSupportPackages | kNavAllFilesInPopup; if (multiple) { - diagOptions.optionFlags += kNavAllowMultipleFiles; + options.optionFlags |= kNavAllowMultipleFiles; + } + options.modality = kWindowModalityAppModal; + if (parent && ((TkWindow*)parent)->window != None && + TkMacOSXHostToplevelExists(parent)) { + options.parentWindow = GetWindowFromPort(TkMacOSXGetDrawablePort( + Tk_WindowId(parent))); + if (options.parentWindow) { + options.modality = kWindowModalityWindowModal; + data.sheet = 1; + } } - diagOptions.modality = kWindowModalityAppModal; - if (ofdPtr != NULL && ofdPtr->usePopup) { + /* + * Now process the selection list. We have to use the popupExtension + * to fill the menu. + */ + if (ofdPtr && ofdPtr->usePopup) { FileFilter *filterPtr; filterPtr = ofdPtr->fl.filters; @@ -758,13 +788,12 @@ NavServicesGetFile( ofdPtr->usePopup = 0; } } - - if (ofdPtr != NULL && ofdPtr->usePopup) { + if (ofdPtr && ofdPtr->usePopup) { FileFilter *filterPtr; int index = 0; ofdPtr->curType = 0; - menuItemNames = (CFStringRef *)ckalloc(ofdPtr->fl.numFilters + menuItemNames = (CFStringRef *) ckalloc(ofdPtr->fl.numFilters * sizeof(CFStringRef)); for (filterPtr = ofdPtr->fl.filters; filterPtr != NULL; @@ -772,98 +801,60 @@ NavServicesGetFile( menuItemNames[index] = CFStringCreateWithCString(NULL, filterPtr->name, kCFStringEncodingUTF8); } - diagOptions.popupExtension = CFArrayCreate(NULL, + options.popupExtension = CFArrayCreate(NULL, (const void **) menuItemNames, ofdPtr->fl.numFilters, NULL); } else { - diagOptions.optionFlags += kNavNoTypePopup; - diagOptions.popupExtension = NULL; + options.optionFlags |= kNavNoTypePopup; + options.popupExtension = NULL; } - - /* - * This is required to allow App packages to be selectable in the - * file dialogs... - */ - - diagOptions.optionFlags += kNavSupportPackages; - - diagOptions.clientName = CFStringCreateWithCString(NULL, "Wish", kCFStringEncodingUTF8); - diagOptions.message = message; - diagOptions.windowTitle = title; + options.clientName = CFSTR("Wish"); + options.message = message; + options.windowTitle = title; if (initialFile) { - diagOptions.saveFileName = CFStringCreateWithCString(NULL, + options.saveFileName = CFStringCreateWithCString(NULL, initialFile, kCFStringEncodingUTF8); } else { - diagOptions.saveFileName = NULL; + options.saveFileName = NULL; } - - diagOptions.actionButtonLabel = NULL; - diagOptions.cancelButtonLabel = NULL; - diagOptions.preferenceKey = 0; - - /* - * Now process the selection list. We have to use the popupExtension - * to fill the menu. - */ - if (isOpen == OPEN_FILE) { - err = NavCreateGetFileDialog(&diagOptions, - NULL, - openFileEventUPP, - NULL, - openFileFilterUPP, - ofdPtr, - &dialogRef); - if (err != noErr) { -#ifdef TK_MAC_DEBUG - fprintf(stderr,"NavCreateGetFileDialog failed, %d\n", err); -#endif - dialogRef = NULL; - } + data.ofdPtr = ofdPtr; + err = ChkErr(NavCreateGetFileDialog, &options, NULL, + openFileEventUPP, NULL, openFileFilterUPP, &data, &dialogRef); } else if (isOpen == SAVE_FILE) { - err = NavCreatePutFileDialog(&diagOptions, 'TEXT', 'WIsH', - openFileEventUPP, NULL, &dialogRef); - if (err!=noErr){ -#ifdef TK_MAC_DEBUG - fprintf(stderr,"NavCreatePutFileDialog failed, %d\n", err); -#endif - dialogRef = NULL; - } + err = ChkErr(NavCreatePutFileDialog, &options, 'TEXT', 'WIsH', + openFileEventUPP, &data, &dialogRef); } else if (isOpen == CHOOSE_FOLDER) { - err = NavCreateChooseFolderDialog(&diagOptions, openFileEventUPP, - openFileFilterUPP, NULL, &dialogRef); - if (err!=noErr){ -#ifdef TK_MAC_DEBUG - fprintf(stderr,"NavCreateChooseFolderDialog failed, %d\n", err); -#endif - dialogRef = NULL; - } + err = ChkErr(NavCreateChooseFolderDialog, &options, + openFileEventUPP, openFileFilterUPP, &data, &dialogRef); } - - if (dialogRef) { - if (initialDescPtr != NULL) { - NavCustomControl (dialogRef, kNavCtlSetLocation, initialDescPtr); + if (err == noErr && dialogRef) { + if (initialDescPtr) { + ChkErr(NavCustomControl, dialogRef, kNavCtlSetLocation, + initialDescPtr); } - if ((selectDescPtr != NULL) - && (selectDescPtr->descriptorType != typeNull)) { - NavCustomControl(dialogRef, kNavCtlSetSelection, selectDescPtr); + if (selectDescPtr && selectDescPtr->descriptorType != typeNull) { + ChkErr(NavCustomControl, dialogRef, kNavCtlSetSelection, + selectDescPtr); } - - if ((err = NavDialogRun(dialogRef)) != noErr){ -#ifdef TK_MAC_DEBUG - fprintf(stderr,"NavDialogRun failed, %d\n", err); -#endif - } else { - if ((err = NavDialogGetReply(dialogRef, &theReply)) != noErr) { -#ifdef TK_MAC_DEBUG - fprintf(stderr,"NavGetReply failed, %d\n", err); -#endif + TkMacOSXTrackingLoop(1); + err = ChkErr(NavDialogRun, dialogRef); + if (err == noErr) { + if (data.sheet) { + data.dialogWindow = NavDialogGetWindow(dialogRef); + ChkErr(GetWindowModality, data.dialogWindow, + &data.origModality, &data.origUnavailWindow); + ChkErr(SetWindowModality, data.dialogWindow, + kWindowModalityAppModal, NULL); + ChkErr(RunAppModalLoopForWindow, data.dialogWindow); } + err = data.err; } + TkMacOSXTrackingLoop(0); } /* * Most commands assume that the file dialogs return a single - * item, not a list. So only build a list if multiple is true... + * item, not a list. So only build a list if multiple is true... */ if (err == noErr) { if (multiple) { @@ -875,55 +866,51 @@ NavServicesGetFile( err = memFullErr; } } - if (theReply.validRecord && err == noErr) { + if (err == noErr && data.reply.validRecord) { AEDesc resultDesc; long count; - FSRef fsRef; - char pathPtr[1024]; - int pathValid = 0; - err = AECountItems(&theReply.selection, &count); + FSRef fsRef; + char pathPtr[PATH_MAX + 1]; + + err = ChkErr(AECountItems, &data.reply.selection, &count); if (err == noErr) { long i; + for (i = 1; i <= count; i++) { - err = AEGetNthDesc(&theReply.selection, - i, typeFSRef, NULL, &resultDesc); - pathValid = 0; + err = ChkErr(AEGetNthDesc, &data.reply.selection, i, + typeFSRef, NULL, &resultDesc); if (err == noErr) { - if ((err = AEGetDescData(&resultDesc, &fsRef, sizeof(fsRef))) - != noErr) { -#ifdef TK_MAC_DEBUG - fprintf(stderr,"AEGetDescData failed %d\n", err); -#endif - } else { - if ((err = FSRefMakePath(&fsRef, (unsigned char*) pathPtr, 1024))) { -#ifdef TK_MAC_DEBUG - fprintf(stderr,"FSRefMakePath failed, %d\n", err); -#endif - } else { + err = ChkErr(AEGetDescData, &resultDesc, &fsRef, + sizeof(fsRef)); + if (err == noErr) { + err = ChkErr(FSRefMakePath, &fsRef, (unsigned char*) + pathPtr, PATH_MAX + 1); + if (err == noErr) { + int pathValid = 0; + if (isOpen == SAVE_FILE) { - CFStringRef saveNameRef; - char saveName [1024]; - if ((saveNameRef = NavDialogGetSaveFileName(dialogRef))) { - if (CFStringGetCString(saveNameRef, saveName, - 1024, kCFStringEncodingUTF8)) { - if (strlen(pathPtr) + strlen(saveName) < 1023) { + if (data.saveNameRef) { + char saveName [PATH_MAX + 1]; + + if (CFStringGetCString(data.saveNameRef, + saveName, PATH_MAX + 1, + kCFStringEncodingUTF8)) { + if (strlen(pathPtr) + strlen(saveName) + < PATH_MAX) { strcat(pathPtr, "/"); strcat(pathPtr, saveName); pathValid = 1; } else { -#ifdef TK_MAC_DEBUG - fprintf(stderr, "Path name too long\n"); -#endif + TkMacOSXDbgMsg("Path name too " + "long"); } } else { -#ifdef TK_MAC_DEBUG - fprintf(stderr, "CFStringGetCString failed\n"); -#endif + TkMacOSXDbgMsg("CFStringGetCString " + "failed"); } } else { -#ifdef TK_MAC_DEBUG - fprintf(stderr, "NavDialogGetSaveFileName failed\n"); -#endif + TkMacOSXDbgMsg("NavDialogGetSaveFileName " + "failed"); } } else { pathValid = 1; @@ -938,73 +925,137 @@ NavServicesGetFile( } } } - AEDisposeDesc(&resultDesc); + ChkErr(AEDisposeDesc, &resultDesc); } } - } - err = NavDisposeReply(&theReply); - Tcl_SetObjResult(interp, theResult); - result = TCL_OK; + } + Tcl_SetObjResult(interp, theResult); + result = TCL_OK; } else if (err == userCanceledErr) { result = TCL_OK; - } else { - result = TCL_ERROR; } /* - * Clean up any allocated strings - * dispose of things in reverse order of creation + * Clean up any allocated memory. */ - if (diagOptions.windowTitle) { - CFRelease(diagOptions.windowTitle); + if (data.reply.validRecord) { + ChkErr(NavDisposeReply, &data.reply); } - if (diagOptions.saveFileName) { - CFRelease(diagOptions.saveFileName); + if (data.saveNameRef) { + CFRelease(data.saveNameRef); } - if (diagOptions.message) { - CFRelease(diagOptions.message); + if (options.saveFileName) { + CFRelease(options.saveFileName); } - if (diagOptions.clientName) { - CFRelease(diagOptions.clientName); + if (options.clientName) { + CFRelease(options.clientName); } - /* - * dispose of the CFArray diagOptions.popupExtension - */ - if (menuItemNames) { int i; - for (i = 0;i < ofdPtr->fl.numFilters; i++) { + for (i = 0; i < ofdPtr->fl.numFilters; i++) { CFRelease(menuItemNames[i]); } ckfree((void *)menuItemNames); } - if (diagOptions.popupExtension != NULL) { - CFRelease(diagOptions.popupExtension); + if (options.popupExtension) { + CFRelease(options.popupExtension); } - return result; } + +/* + *---------------------------------------------------------------------- + * + * OpenEventProc -- + * + * NavServices event handling callback. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +pascal void +OpenEventProc( + NavEventCallbackMessage callBackSelector, + NavCBRecPtr callBackParams, + NavCallBackUserData callBackUD) +{ + NavHandlerUserData *data = (NavHandlerUserData*) callBackUD; -static pascal Boolean + switch (callBackSelector) { + case kNavCBPopupMenuSelect: + data->ofdPtr->curType = ((NavMenuItemSpec *) + callBackParams->eventData.eventDataParms.param)->menuType; + break; + case kNavCBAccept: + case kNavCBCancel: + if (data->sheet) { + ChkErr(QuitAppModalLoopForWindow, data->dialogWindow); + ChkErr(SetWindowModality, data->dialogWindow, + data->origModality, data->origUnavailWindow); + } + break; + case kNavCBUserAction: + if (data->reply.validRecord) { + ChkErr(NavDisposeReply, &data->reply); + data->reply.validRecord = 0; + } + data->err = NavDialogGetReply(callBackParams->context, + &data->reply); + if (callBackParams->userAction == kNavUserActionSaveAs) { + data->saveNameRef = NavDialogGetSaveFileName( + callBackParams->context); + if (data->saveNameRef) { + CFRetain(data->saveNameRef); + } + } + break; + case kNavCBTerminate: + NavDialogDispose(callBackParams->context); + break; + case kNavCBEvent: + TkMacOSXRunTclEventLoop(); + break; + } +} + +/* + *---------------------------------------------------------------------- + * + * OpenFileFilterProc -- + * + * NavServices file filter callback. + * + * Results: + * Whether to use the file in question. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +pascal Boolean OpenFileFilterProc( AEDesc* theItem, void* info, NavCallBackUserData callBackUD, NavFilterModes filterMode) { - OpenFileData *ofdPtr = (OpenFileData *) callBackUD; + OpenFileData *ofdPtr = ((NavHandlerUserData*) callBackUD)->ofdPtr; + int result = MATCHED; - if (!ofdPtr || !ofdPtr->usePopup) { - return true; - } else { - if (ofdPtr->fl.numFilters == 0) { - return true; - } else { + if (ofdPtr && ofdPtr->usePopup) { + if (ofdPtr->fl.numFilters > 0) { if ((theItem->descriptorType == typeFSS) - || (theItem->descriptorType = typeFSRef)) { + || (theItem->descriptorType == typeFSRef)) { NavFileOrFolderInfo* theInfo = (NavFileOrFolderInfo *) info; char fileName[256]; - int result; if (!theInfo->isFolder) { OSType fileType; @@ -1019,7 +1070,7 @@ OpenFileFilterProc( if (theItem->descriptorType == typeFSS) { int len; - fileNamePtr = (((FSSpec *) *theItem->dataHandle)->name); + fileNamePtr = ((FSSpec *) *theItem->dataHandle)->name; len = fileNamePtr[0]; strncpy(fileName, (char*) fileNamePtr + 1, len); fileName[len] = '\0'; @@ -1029,15 +1080,15 @@ OpenFileFilterProc( OSStatus err; FSRef *theRef = (FSRef *) *theItem->dataHandle; HFSUniStr255 uniFileName; - err = FSGetCatalogInfo (theRef, kFSCatInfoNone, NULL, - &uniFileName, NULL, NULL); + err = ChkErr(FSGetCatalogInfo, theRef, kFSCatInfoNone, + NULL, &uniFileName, NULL, NULL); if (err == noErr) { Tcl_UniCharToUtfDString ( (Tcl_UniChar *) uniFileName.unicode, - uniFileName.length, - &fileNameDString); - fileNamePtr = (unsigned char*) Tcl_DStringValue(&fileNameDString); + uniFileName.length, &fileNameDString); + fileNamePtr = (unsigned char*) + Tcl_DStringValue(&fileNameDString); } else { fileNamePtr = NULL; } @@ -1052,7 +1103,7 @@ OpenFileFilterProc( result = MatchOneType(fileNamePtr, fileType, ofdPtr, filterPtr); } else { - result = false; + result = UNMATCHED; } } else { /* @@ -1071,42 +1122,12 @@ OpenFileFilterProc( } } } - Tcl_DStringFree (&fileNameDString); - return (result == MATCHED); - } else { - return true; } } } - - return true; - } -} - -pascal void -OpenEventProc( - NavEventCallbackMessage callBackSelector, - NavCBRecPtr callBackParams, - NavCallBackUserData callBackUD) -{ - NavMenuItemSpec *chosenItem; - OpenFileData *ofd = (OpenFileData *) callBackUD; - static SInt32 otherEvent = ~(kNavCBCustomize|kNavCBStart|kNavCBTerminate - |kNavCBNewLocation|kNavCBShowDesktop|kNavCBSelectEntry|kNavCBAccept - |kNavCBCancel|kNavCBAdjustPreview); - - if (callBackSelector == kNavCBPopupMenuSelect) { - chosenItem = (NavMenuItemSpec *) callBackParams->eventData.eventDataParms.param; - ofd->curType = chosenItem->menuType; - } else if (callBackSelector == kNavCBAdjustRect - || (callBackSelector & otherEvent) != 0) { - while (Tcl_DoOneEvent(TCL_IDLE_EVENTS - | TCL_DONT_WAIT - | TCL_WINDOW_EVENTS)) { - /* Empty Body */ - } } + return (result == MATCHED); } /* @@ -1114,27 +1135,28 @@ OpenEventProc( * * MatchOneType -- * - * Match a file with one file type in the list of file types. + * Match a file with one file type in the list of file types. * * Results: - * Returns MATCHED if the file matches with the file type; returns - * UNMATCHED otherwise. + * Returns MATCHED if the file matches with the file type; returns + * UNMATCHED otherwise. * * Side effects: - * None + * None * *---------------------------------------------------------------------- */ -static Boolean +Boolean MatchOneType( - StringPtr fileNamePtr, /* Name of the file */ - OSType fileType, /* Type of the file, 0 means there was no specified type. */ - OpenFileData * ofdPtr, /* Information about this file dialog */ - FileFilter * filterPtr) /* Match the file described by pb against - * this filter */ + StringPtr fileNamePtr, /* Name of the file */ + OSType fileType, /* Type of the file, 0 means there was no + * specified type. */ + OpenFileData *ofdPtr, /* Information about this file dialog */ + FileFilter *filterPtr) /* Match the file described by pb against this + * filter */ { - FileFilterClause * clausePtr; + FileFilterClause *clausePtr; /* * A file matches with a file type if it matches with at least one @@ -1155,10 +1177,10 @@ MatchOneType( for (clausePtr = filterPtr->clauses; clausePtr; clausePtr = clausePtr->next) { - int macMatched = 0; + int macMatched = 0; int globMatched = 0; - GlobPattern * globPtr; - MacFileType * mfPtr; + GlobPattern *globPtr; + MacFileType *mfPtr; if (clausePtr->patterns == NULL) { globMatched = 1; @@ -1196,10 +1218,10 @@ MatchOneType( goto glob_unmatched; } - glob_unmatched: + glob_unmatched: continue; - glob_matched: + glob_matched: globMatched = 1; break; } @@ -1213,11 +1235,11 @@ MatchOneType( /* * On Mac OS X, it is not uncommon for files to have NO - * file type. But folks with Tcl code on Classic MacOS pretty - * much assume that a generic file will have type TEXT. So + * file type. But folks with Tcl code on Classic MacOS pretty + * much assume that a generic file will have type TEXT. So * if we were strict about matching types when the source file * had NO type set, they would have to add another rule always - * with no fileType. To avoid that, we pass the macMatch side + * with no fileType. To avoid that, we pass the macMatch side * of the test if no fileType is set. */ @@ -1228,146 +1250,126 @@ MatchOneType( return UNMATCHED; } - + /* *---------------------------------------------------------------------- * * TkAboutDlg -- * - * Displays the default Tk About box. This code uses Macintosh - * resources to define the content of the About Box. + * Displays the default Tk About box. This code uses Macintosh + * resources to define the content of the About Box. * * Results: - * None. + * None. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ void -TkAboutDlg() +TkAboutDlg(void) { DialogPtr aboutDlog; WindowRef windowRef; short itemHit = -9; - aboutDlog = GetNewDialog(128, NULL, (void *) (-1)); - + aboutDlog = GetNewDialog(TK_DEFAULT_ABOUT, NULL, (void *) (-1)); if (!aboutDlog) { return; } - windowRef = GetDialogWindow(aboutDlog); SelectWindow(windowRef); - + TkMacOSXTrackingLoop(1); while (itemHit != 1) { ModalDialog(NULL, &itemHit); } + TkMacOSXTrackingLoop(0); DisposeDialog(aboutDlog); - aboutDlog = NULL; - SelectWindow(ActiveNonFloatingWindow()); - - return; } - + /* *---------------------------------------------------------------------- * * Tk_MessageBoxObjCmd -- * - * Implements the tk_messageBox in native Mac OS X style. + * Implements the tk_messageBox in native Mac OS X style. * * Results: - * A standard Tcl result. + * A standard Tcl result. * * Side effects: - * none + * none * *---------------------------------------------------------------------- */ int Tk_MessageBoxObjCmd( - ClientData clientData, /* Main window associated with interpreter. */ - Tcl_Interp *interp, /* Current interpreter. */ - int objc, /* Number of arguments. */ - Tcl_Obj *CONST objv[]) /* Argument objects. */ + ClientData clientData, /* Main window associated with interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int objc, /* Number of arguments. */ + Tcl_Obj *CONST objv[]) /* Argument objects. */ { - Tk_Window tkwin = (Tk_Window) clientData; + Tk_Window tkwin = (Tk_Window) clientData; AlertStdCFStringAlertParamRec paramCFStringRec; - AlertType alertType; - DialogRef dialogRef; - CFStringRef messageTextCF = NULL; - CFStringRef finemessageTextCF = NULL; - OSErr osError; - SInt16 itemHit; - Boolean haveDefaultOption = false; - Boolean haveParentOption = false; - char *str; - int index; - int defaultButtonIndex; - int defaultNativeButtonIndex; /* 1, 2, 3: right to left. */ - int typeIndex; - int i; - int indexDefaultOption = 0; - int result = TCL_OK; - - static CONST char *movableAlertStrings[] = { - "-default", "-detail", "-icon", - "-message", "-parent", - "-title", "-type", - (char *)NULL + AlertType alertType; + DialogRef dialogRef; + CFStringRef messageTextCF = NULL, finemessageTextCF = NULL; + OSStatus err; + SInt16 itemHit; + Boolean haveDefaultOption = false, haveParentOption = false; + char *str; + int index, defaultButtonIndex; + int defaultNativeButtonIndex; /* 1, 2, 3: right to left */ + int typeIndex, i, indexDefaultOption = 0, result = TCL_ERROR; + + static const char *movableAlertStrings[] = { + "-default", "-detail", "-icon", "-message", "-parent", "-title", + "-type", NULL }; - static CONST char *movableTypeStrings[] = { - "abortretryignore", "ok", - "okcancel", "retrycancel", - "yesno", "yesnocancel", - (char *)NULL + static const char *movableTypeStrings[] = { + "abortretryignore", "ok", "okcancel", "retrycancel", "yesno", + "yesnocancel", NULL }; - static CONST char *movableButtonStrings[] = { - "abort", "retry", "ignore", - "ok", "cancel", "yes", "no", - (char *)NULL + static const char *movableButtonStrings[] = { + "abort", "retry", "ignore", "ok", "cancel", "yes", "no", NULL }; - static CONST char *movableIconStrings[] = { - "error", "info", "question", "warning", - (char *)NULL + static const char *movableIconStrings[] = { + "error", "info", "question", "warning", NULL }; enum movableAlertOptions { - ALERT_DEFAULT, ALERT_DETAIL, ALERT_ICON, - ALERT_MESSAGE, ALERT_PARENT, + ALERT_DEFAULT, ALERT_DETAIL, ALERT_ICON, ALERT_MESSAGE, ALERT_PARENT, ALERT_TITLE, ALERT_TYPE }; enum movableTypeOptions { - TYPE_ABORTRETRYIGNORE, TYPE_OK, - TYPE_OKCANCEL, TYPE_RETRYCANCEL, + TYPE_ABORTRETRYIGNORE, TYPE_OK, TYPE_OKCANCEL, TYPE_RETRYCANCEL, TYPE_YESNO, TYPE_YESNOCANCEL }; enum movableButtonOptions { - TEXT_ABORT, TEXT_RETRY, TEXT_IGNORE, - TEXT_OK, TEXT_CANCEL, TEXT_YES, TEXT_NO + TEXT_ABORT, TEXT_RETRY, TEXT_IGNORE, TEXT_OK, TEXT_CANCEL, TEXT_YES, + TEXT_NO }; enum movableIconOptions { ICON_ERROR, ICON_INFO, ICON_QUESTION, ICON_WARNING }; /* - * Need to map from 'movableButtonStrings' and its corresponding integer index, - * to the native button index, which is 1, 2, 3, from right to left. + * Need to map from 'movableButtonStrings' and its corresponding integer, + * index to the native button index, which is 1, 2, 3, from right to left. * This is necessary to do for each separate '-type' of button sets. */ - short buttonIndexAndTypeToNativeButtonIndex[][7] = { - /* abort retry ignore ok cancel yes no */ - {1, 2, 3, 0, 0, 0, 0}, /* abortretryignore */ - {0, 0, 0, 1, 0, 0, 0}, /* ok */ - {0, 0, 0, 1, 2, 0, 0}, /* okcancel */ - {0, 1, 0, 0, 2, 0, 0}, /* retrycancel */ - {0, 0, 0, 0, 0, 1, 2}, /* yesno */ - {0, 0, 0, 0, 3, 1, 2}, /* yesnocancel */ + short buttonIndexAndTypeToNativeButtonIndex[][7] = { + /* abort retry ignore ok cancel yes no */ + {1, 2, 3, 0, 0, 0, 0}, /* abortretryignore */ + {0, 0, 0, 1, 0, 0, 0}, /* ok */ + {0, 0, 0, 1, 2, 0, 0}, /* okcancel */ + {0, 1, 0, 0, 2, 0, 0}, /* retrycancel */ + {0, 0, 0, 0, 0, 1, 2}, /* yesno */ + {0, 0, 0, 0, 3, 1, 2}, /* yesnocancel */ }; /* @@ -1375,137 +1377,137 @@ Tk_MessageBoxObjCmd( * descriptive button text string index. */ - short nativeButtonIndexAndTypeToButtonIndex[][4] = { - {-1, 0, 1, 2}, /* abortretryignore */ - {-1, 3, 0, 0}, /* ok */ - {-1, 3, 4, 0}, /* okcancel */ - {-1, 1, 4, 0}, /* retrycancel */ - {-1, 5, 6, 0}, /* yesno */ - {-1, 5, 6, 4}, /* yesnocancel */ + short nativeButtonIndexAndTypeToButtonIndex[][4] = { + {-1, 0, 1, 2}, /* abortretryignore */ + {-1, 3, 0, 0}, /* ok */ + {-1, 3, 4, 0}, /* okcancel */ + {-1, 1, 4, 0}, /* retrycancel */ + {-1, 5, 6, 0}, /* yesno */ + {-1, 5, 6, 4}, /* yesnocancel */ }; alertType = kAlertPlainAlert; typeIndex = TYPE_OK; - GetStandardAlertDefaultParams(¶mCFStringRec, kStdCFStringAlertVersionOne); + ChkErr(GetStandardAlertDefaultParams, ¶mCFStringRec, + kStdCFStringAlertVersionOne); paramCFStringRec.movable = true; paramCFStringRec.helpButton = false; paramCFStringRec.defaultButton = kAlertStdAlertOKButton; paramCFStringRec.cancelButton = kAlertStdAlertCancelButton; for (i = 1; i < objc; i += 2) { - int iconIndex; - char *string; + int iconIndex; + char *string; if (Tcl_GetIndexFromObj(interp, objv[i], movableAlertStrings, "option", - TCL_EXACT, &index) != TCL_OK) { - result = TCL_ERROR; + TCL_EXACT, &index) != TCL_OK) { goto end; } if (i + 1 == objc) { - string = Tcl_GetStringFromObj(objv[i], NULL); + string = Tcl_GetString(objv[i]); Tcl_AppendResult(interp, "value for \"", string, "\" missing", - (char *) NULL); - result = TCL_ERROR; + NULL); goto end; } switch (index) { - case ALERT_DEFAULT: - - /* - * Need to postpone processing of this option until we are - * sure to know the '-type' as well. - */ - - haveDefaultOption = true; - indexDefaultOption = i; - break; + /* + * Need to postpone processing of this option until we are + * sure to know the '-type' as well. + */ + haveDefaultOption = true; + indexDefaultOption = i; + break; case ALERT_DETAIL: - str = Tcl_GetStringFromObj(objv[i + 1], NULL); - finemessageTextCF = CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8); - break; + str = Tcl_GetString(objv[i + 1]); + finemessageTextCF = CFStringCreateWithCString(NULL, str, + kCFStringEncodingUTF8); + break; case ALERT_ICON: - /* not sure about UTF translation here... */ - if (Tcl_GetIndexFromObj(interp, objv[i + 1], movableIconStrings, - "value", TCL_EXACT, &iconIndex) != TCL_OK) { - result = TCL_ERROR; - goto end; - } - switch (iconIndex) { - case ICON_ERROR: - alertType = kAlertStopAlert; - break; - case ICON_INFO: - alertType = kAlertNoteAlert; - break; - case ICON_QUESTION: - alertType = kAlertCautionAlert; - break; - case ICON_WARNING: - alertType = kAlertCautionAlert; + if (Tcl_GetIndexFromObj(interp, objv[i + 1], + movableIconStrings, "value", TCL_EXACT, &iconIndex) + != TCL_OK) { + goto end; + } + switch (iconIndex) { + case ICON_ERROR: + alertType = kAlertStopAlert; + break; + case ICON_INFO: + alertType = kAlertNoteAlert; + break; + case ICON_QUESTION: + alertType = kAlertCautionAlert; + break; + case ICON_WARNING: + alertType = kAlertCautionAlert; + break; + } break; - } - break; case ALERT_MESSAGE: - str = Tcl_GetStringFromObj(objv[i + 1], NULL); - messageTextCF = CFStringCreateWithCString(NULL, str, kCFStringEncodingUTF8); - break; + str = Tcl_GetString(objv[i + 1]); + messageTextCF = CFStringCreateWithCString(NULL, str, + kCFStringEncodingUTF8); + break; case ALERT_PARENT: - str = Tcl_GetStringFromObj(objv[i + 1], NULL); - tkwin = Tk_NameToWindow(interp, str, tkwin); - if (tkwin == NULL) { - result = TCL_ERROR; - goto end; - } - haveParentOption = true; - break; + str = Tcl_GetString(objv[i + 1]); + tkwin = Tk_NameToWindow(interp, str, tkwin); + if (tkwin == NULL) { + goto end; + } + if (((TkWindow*)tkwin)->window != None && + TkMacOSXHostToplevelExists(tkwin)) { + haveParentOption = true; + } + break; case ALERT_TITLE: - break; + break; case ALERT_TYPE: - /* not sure about UTF translation here... */ - if (Tcl_GetIndexFromObj(interp, objv[i + 1], movableTypeStrings, - "value", TCL_EXACT, &typeIndex) != TCL_OK) { - result = TCL_ERROR; - goto end; - } - switch (typeIndex) { - case TYPE_ABORTRETRYIGNORE: - paramCFStringRec.defaultText = CFSTR("Abort"); - paramCFStringRec.cancelText = CFSTR("Retry"); - paramCFStringRec.otherText = CFSTR("Ignore"); - paramCFStringRec.cancelButton = kAlertStdAlertOtherButton; - break; - case TYPE_OK: - paramCFStringRec.defaultText = CFSTR("OK"); - break; - case TYPE_OKCANCEL: - paramCFStringRec.defaultText = CFSTR("OK"); - paramCFStringRec.cancelText = CFSTR("Cancel"); - break; - case TYPE_RETRYCANCEL: - paramCFStringRec.defaultText = CFSTR("Retry"); - paramCFStringRec.cancelText = CFSTR("Cancel"); - break; - case TYPE_YESNO: - paramCFStringRec.defaultText = CFSTR("Yes"); - paramCFStringRec.cancelText = CFSTR("No"); - break; - case TYPE_YESNOCANCEL: - paramCFStringRec.defaultText = CFSTR("Yes"); - paramCFStringRec.cancelText = CFSTR("No"); - paramCFStringRec.otherText = CFSTR("Cancel"); - paramCFStringRec.cancelButton = kAlertStdAlertOtherButton; + if (Tcl_GetIndexFromObj(interp, objv[i + 1],\ + movableTypeStrings, "value", TCL_EXACT, &typeIndex) + != TCL_OK) { + goto end; + } + switch (typeIndex) { + case TYPE_ABORTRETRYIGNORE: + paramCFStringRec.defaultText = CFSTR("Abort"); + paramCFStringRec.cancelText = CFSTR("Retry"); + paramCFStringRec.otherText = CFSTR("Ignore"); + paramCFStringRec.cancelButton = + kAlertStdAlertOtherButton; + break; + case TYPE_OK: + paramCFStringRec.defaultText = CFSTR("OK"); + break; + case TYPE_OKCANCEL: + paramCFStringRec.defaultText = CFSTR("OK"); + paramCFStringRec.cancelText = CFSTR("Cancel"); + break; + case TYPE_RETRYCANCEL: + paramCFStringRec.defaultText = CFSTR("Retry"); + paramCFStringRec.cancelText = CFSTR("Cancel"); + break; + case TYPE_YESNO: + paramCFStringRec.defaultText = CFSTR("Yes"); + paramCFStringRec.cancelText = CFSTR("No"); + break; + case TYPE_YESNOCANCEL: + paramCFStringRec.defaultText = CFSTR("Yes"); + paramCFStringRec.cancelText = CFSTR("No"); + paramCFStringRec.otherText = CFSTR("Cancel"); + paramCFStringRec.cancelButton = + kAlertStdAlertOtherButton; + break; + } break; - } - break; } } @@ -1516,22 +1518,22 @@ Tk_MessageBoxObjCmd( * we do this here. */ - str = Tcl_GetStringFromObj(objv[indexDefaultOption + 1], NULL); + str = Tcl_GetString(objv[indexDefaultOption + 1]); if (Tcl_GetIndexFromObj(interp, objv[indexDefaultOption + 1], - movableButtonStrings, "value", TCL_EXACT, - &defaultButtonIndex) != TCL_OK) { - result = TCL_ERROR; + movableButtonStrings, "value", TCL_EXACT, &defaultButtonIndex) + != TCL_OK) { goto end; } - /* Need to map from "ok" etc. to 1, 2, 3, right to left. */ + /* + * Need to map from "ok" etc. to 1, 2, 3, right to left. + */ defaultNativeButtonIndex = buttonIndexAndTypeToNativeButtonIndex[typeIndex][defaultButtonIndex]; if (defaultNativeButtonIndex == 0) { Tcl_SetObjResult(interp, - Tcl_NewStringObj("Illegal default option", -1)); - result = TCL_ERROR; + Tcl_NewStringObj("Illegal default option", -1)); goto end; } paramCFStringRec.defaultButton = defaultNativeButtonIndex; @@ -1539,89 +1541,83 @@ Tk_MessageBoxObjCmd( paramCFStringRec.cancelButton = 0; } } - SetThemeCursor(kThemeArrowCursor); + ChkErr(SetThemeCursor, kThemeArrowCursor); if (haveParentOption) { - TkWindow *winPtr; - WindowRef windowRef; - EventTargetRef notifyTarget; - EventHandlerUPP handler; - CallbackUserData data; + AlertHandlerUserData data; + static EventHandlerUPP handler = NULL; + WindowRef windowRef; const EventTypeSpec kEvents[] = { {kEventClassCommand, kEventProcessCommand} }; - winPtr = (TkWindow *) tkwin; - - /* - * Create the underlying Mac window for this Tk window. - */ - - windowRef = GetWindowFromPort( - TkMacOSXGetDrawablePort(Tk_WindowId(tkwin))); - notifyTarget = GetWindowEventTarget(windowRef); - osError = CreateStandardSheet(alertType, messageTextCF, - finemessageTextCF, ¶mCFStringRec, - notifyTarget, &dialogRef); - if(osError != noErr) { - result = TCL_ERROR; + bzero(&data, sizeof(data)); + if (!handler) { + handler = NewEventHandlerUPP(AlertHandler); + } + windowRef = GetWindowFromPort(TkMacOSXGetDrawablePort( + Tk_WindowId(tkwin))); + if (!windowRef) { goto end; } - data.windowRef = windowRef; - data.buttonIndex = 1; - handler = NewEventHandlerUPP(AlertHandler); - InstallEventHandler(notifyTarget, handler, - GetEventTypeCount(kEvents), - kEvents, &data, NULL); - osError = ShowSheetWindow(GetDialogWindow(dialogRef), windowRef); - if(osError != noErr) { - result = TCL_ERROR; + err = ChkErr(CreateStandardSheet, alertType, messageTextCF, + finemessageTextCF, ¶mCFStringRec, NULL, &dialogRef); + if(err != noErr) { goto end; } - osError = RunAppModalLoopForWindow(windowRef); - if (osError != noErr) { - result = TCL_ERROR; + data.dialogWindow = GetDialogWindow(dialogRef); + err = ChkErr(ShowSheetWindow, data.dialogWindow, windowRef); + if(err != noErr) { + DisposeDialog(dialogRef); goto end; } + ChkErr(GetWindowModality, data.dialogWindow, &data.origModality, + &data.origUnavailWindow); + ChkErr(SetWindowModality, data.dialogWindow, kWindowModalityAppModal, + NULL); + ChkErr(InstallEventHandler, GetWindowEventTarget(data.dialogWindow), + handler, GetEventTypeCount(kEvents), kEvents, &data, + &data.handlerRef); + TkMacOSXTrackingLoop(1); + ChkErr(RunAppModalLoopForWindow, data.dialogWindow); + TkMacOSXTrackingLoop(0); itemHit = data.buttonIndex; - DisposeEventHandlerUPP(handler); } else { - osError = CreateStandardAlert(alertType, messageTextCF, - finemessageTextCF, ¶mCFStringRec, &dialogRef); - if(osError != noErr) { - result = TCL_ERROR; + err = ChkErr(CreateStandardAlert, alertType, messageTextCF, + finemessageTextCF, ¶mCFStringRec, &dialogRef); + if(err != noErr) { goto end; } - osError = RunStandardAlert(dialogRef, NULL, &itemHit); - if (osError != noErr) { - result = TCL_ERROR; + TkMacOSXTrackingLoop(1); + err = ChkErr(RunStandardAlert, dialogRef, NULL, &itemHit); + TkMacOSXTrackingLoop(0); + if (err != noErr) { goto end; } } - if(osError == noErr) { - int ind; + if (err == noErr) { + int ind; /* * Map 'itemHit' (1, 2, 3) to descriptive text string. */ ind = nativeButtonIndexAndTypeToButtonIndex[typeIndex][itemHit]; - Tcl_SetObjResult(interp, - Tcl_NewStringObj(movableButtonStrings[ind], -1)); - } else { - result = TCL_ERROR; + Tcl_SetObjResult(interp, Tcl_NewStringObj(movableButtonStrings[ind], + -1)); + result = TCL_OK; } - end: - if (finemessageTextCF != NULL) { +end: + if (finemessageTextCF) { CFRelease(finemessageTextCF); } - if (messageTextCF != NULL) { + if (messageTextCF) { CFRelease(messageTextCF); } return result; } - + /* *---------------------------------------------------------------------- * @@ -1638,31 +1634,33 @@ Tk_MessageBoxObjCmd( *---------------------------------------------------------------------- */ -static OSStatus -AlertHandler(EventHandlerCallRef callRef, EventRef eventRef, void *userData) +OSStatus +AlertHandler( + EventHandlerCallRef callRef, + EventRef eventRef, + void *userData) { - OSStatus result = eventNotHandledErr; - HICommand cmd; - CallbackUserData *dataPtr = (CallbackUserData *) userData; + AlertHandlerUserData *data = (AlertHandlerUserData *) userData; + HICommand cmd; - GetEventParameter(eventRef, kEventParamDirectObject, typeHICommand, - NULL, sizeof(cmd), NULL, &cmd); + ChkErr(GetEventParameter,eventRef, kEventParamDirectObject, typeHICommand, + NULL, sizeof(cmd), NULL, &cmd); switch (cmd.commandID) { case kHICommandOK: - dataPtr->buttonIndex = 1; - result = noErr; - break; + data->buttonIndex = 1; + break; case kHICommandCancel: - dataPtr->buttonIndex = 2; - result = noErr; - break; + data->buttonIndex = 2; + break; case kHICommandOther: - dataPtr->buttonIndex = 3; - result = noErr; - break; + data->buttonIndex = 3; + break; } - if (result == noErr) { - result = QuitAppModalLoopForWindow(dataPtr->windowRef); + if (data->buttonIndex) { + ChkErr(QuitAppModalLoopForWindow, data->dialogWindow); + ChkErr(RemoveEventHandler, data->handlerRef); + ChkErr(SetWindowModality, data->dialogWindow, + data->origModality, data->origUnavailWindow); } - return result; + return eventNotHandledErr; } diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c index 8ecb7d9..d01a669 100644 --- a/macosx/tkMacOSXDraw.c +++ b/macosx/tkMacOSXDraw.c @@ -1,18 +1,18 @@ -/* +/* * tkMacOSXDraw.c -- * - * This file contains functions that perform drawing to - * Xlib windows. Most of the functions simple emulate - * Xlib functions. + * This file contains functions that perform drawing to + * Xlib windows. Most of the functions simple emulate + * Xlib functions. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. - * Copyright (c) 2006 Daniel A. Steffen + * Copyright (c) 2006-2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXDraw.c,v 1.20 2007/04/21 19:06:37 hobbs Exp $ + * RCS: @(#) $Id: tkMacOSXDraw.c,v 1.21 2007/04/23 21:24:33 das Exp $ */ #include "tkMacOSXInt.h" @@ -24,10 +24,7 @@ #endif */ -#define RGBFLOATRED(c) ((c).red / 65535.0) -#define RGBFLOATGREEN(c) ((c).green / 65535.0) -#define RGBFLOATBLUE(c) ((c).blue / 65535.0) -#define radians(d) ((d) * (M_PI/180.0)) +#define radians(d) ((d) * (M_PI/180.0)) /* * Non-antialiased CG drawing looks better and more like X11 drawing when using @@ -39,8 +36,9 @@ * Temporary regions that can be reused. */ -static RgnHandle tmpRgn = NULL; -static RgnHandle tmpRgn2 = NULL; +RgnHandle tkMacOSXtmpRgn1 = NULL; +RgnHandle tkMacOSXtmpRgn2 = NULL; + static PixPatHandle gPenPat = NULL; static int useCGDrawing = 1; @@ -54,32 +52,29 @@ static int useThemedFrame = 0; * Prototypes for functions used only in this file. */ static unsigned char InvertByte(unsigned char data); -static void TkMacOSXSetUpCGContext(MacDrawable *macWin, CGrafPtr destPort, - GC gc, CGContextRef *contextPtr); -static void TkMacOSXReleaseCGContext(MacDrawable *macWin, CGrafPtr destPort, - CGContextRef *context); + /* *---------------------------------------------------------------------- * * TkMacOSXInitCGDrawing -- * - * Initializes link vars that control CG drawing. + * Initializes link vars that control CG drawing. * * Results: - * None. + * None. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ MODULE_SCOPE int -TkMacOSXInitCGDrawing(interp, enable, limit) - Tcl_Interp *interp; - int enable; - int limit; +TkMacOSXInitCGDrawing( + Tcl_Interp *interp, + int enable, + int limit) { static Boolean initialized = FALSE; @@ -104,15 +99,29 @@ TkMacOSXInitCGDrawing(interp, enable, limit) /* * Piggy-back the themed drawing var init here. */ + if (Tcl_LinkVar(interp, "::tk::mac::useThemedToplevel", - (char *) &useThemedToplevel, TCL_LINK_BOOLEAN) != TCL_OK) { + (char *) &useThemedToplevel, TCL_LINK_BOOLEAN) != TCL_OK) { Tcl_ResetResult(interp); } if (Tcl_LinkVar(interp, "::tk::mac::useThemedFrame", - (char *) &useThemedFrame, TCL_LINK_BOOLEAN) != TCL_OK) { + (char *) &useThemedFrame, TCL_LINK_BOOLEAN) != TCL_OK) { Tcl_ResetResult(interp); } + + if (tkMacOSXtmpRgn1 == NULL) { + tkMacOSXtmpRgn1 = NewRgn(); + } + if (tkMacOSXtmpRgn2 == NULL) { + tkMacOSXtmpRgn2 = NewRgn(); + } } +#ifdef TK_MAC_DEBUG_DRAWING + TkMacOSXInitNamedDebugSymbol(QD, void, QD_DebugPrint, char*); + if (QD_DebugPrint) { + ; /* gdb: b *QD_DebugPrint */ + } +#endif /* TK_MAC_DEBUG_WINDOWS */ return TCL_OK; } @@ -121,41 +130,37 @@ TkMacOSXInitCGDrawing(interp, enable, limit) * * XCopyArea -- * - * Copies data from one drawable to another using block transfer - * routines. + * Copies data from one drawable to another using block transfer + * routines. * * Results: - * None. + * None. * * Side effects: - * Data is moved from a window or bitmap to a second window or - * bitmap. + * Data is moved from a window or bitmap to a second window or + * bitmap. * *---------------------------------------------------------------------- */ void XCopyArea( - Display* display, /* Display. */ - Drawable src, /* Source drawable. */ - Drawable dst, /* Destination drawable. */ - GC gc, /* GC to use. */ - int src_x, /* X & Y, width & height */ - int src_y, /* define the source rectangle */ - unsigned int width, /* the will be copied. */ + Display *display, /* Display. */ + Drawable src, /* Source drawable. */ + Drawable dst, /* Destination drawable. */ + GC gc, /* GC to use. */ + int src_x, /* X & Y, width & height */ + int src_y, /* define the source rectangle */ + unsigned int width, /* the will be copied. */ unsigned int height, - int dest_x, /* Dest X & Y on dest rect. */ + int dest_x, /* Dest X & Y on dest rect. */ int dest_y) { - Rect srcRect, dstRect; - Rect * srcPtr, * dstPtr; - const BitMap * srcBit; - const BitMap * dstBit; - MacDrawable *srcDraw = (MacDrawable *) src; - MacDrawable *dstDraw = (MacDrawable *) dst; - CGrafPtr srcPort, dstPort; - CGrafPtr saveWorld; - GDHandle saveDevice; + Rect srcRect, dstRect, *srcPtr, *dstPtr; + const BitMap *srcBit, *dstBit; + MacDrawable *srcDraw = (MacDrawable *) src, *dstDraw = (MacDrawable *) dst; + CGrafPtr srcPort, dstPort, savePort; + Boolean portChanged; short tmode; RGBColor origForeColor, origBackColor, whiteColor, blackColor; Rect clpRect; @@ -164,8 +169,7 @@ XCopyArea( srcPort = TkMacOSXGetDrawablePort(src); display->request++; - GetGWorld(&saveWorld, &saveDevice); - SetGWorld(dstPort, NULL); + portChanged = QDSwapPort(dstPort, &savePort); GetForeColor(&origForeColor); GetBackColor(&origBackColor); whiteColor.red = 0; @@ -177,9 +181,6 @@ XCopyArea( blackColor.green = 0xFFFF; RGBBackColor(&blackColor); - if (tmpRgn2 == NULL) { - tmpRgn2 = NewRgn(); - } srcPtr = &srcRect; SetRect(&srcRect, (short) (srcDraw->xOff + src_x), (short) (srcDraw->yOff + src_y), @@ -195,18 +196,20 @@ XCopyArea( (short) (dstDraw->yOff + dest_y + height)); } TkMacOSXSetUpClippingRgn(dst); + /* - * We will change the clip rgn in this routine, so we need to - * be able to restore it when we exit. + * We will change the clip rgn in this routine, so we need to + * be able to restore it when we exit. */ - GetClip(tmpRgn2); + TkMacOSXCheckTmpRgnEmpty(2); + GetClip(tkMacOSXtmpRgn2); if (tkPictureIsOpen) { /* * When rendering into a picture, after a call to "OpenCPicture" * the clipping is seriously WRONG and also INCONSISTENT with the * clipping for single plane bitmaps. - * To circumvent this problem, we clip to the whole window + * To circumvent this problem, we clip to the whole window * In this case, would have also clipped to the srcRect * ClipRect(&srcRect); */ @@ -215,23 +218,22 @@ XCopyArea( dstPtr = &srcRect; ClipRect(&clpRect); } - if (!gc->clip_mask) { - } else if (((TkpClipMask*)gc->clip_mask)->type == TKP_CLIP_REGION) { + if (gc->clip_mask && ((TkpClipMask*)gc->clip_mask)->type + == TKP_CLIP_REGION) { RgnHandle clipRgn = (RgnHandle) ((TkpClipMask*)gc->clip_mask)->value.region; - int xOffset = 0, yOffset = 0; - if (tmpRgn == NULL) { - tmpRgn = NewRgn(); - } + if (!tkPictureIsOpen) { xOffset = dstDraw->xOff + gc->clip_x_origin; yOffset = dstDraw->yOff + gc->clip_y_origin; OffsetRgn(clipRgn, xOffset, yOffset); } - GetClip(tmpRgn); - SectRgn(tmpRgn, clipRgn, tmpRgn); - SetClip(tmpRgn); + TkMacOSXCheckTmpRgnEmpty(1); + GetClip(tkMacOSXtmpRgn1); + SectRgn(tkMacOSXtmpRgn1, clipRgn, tkMacOSXtmpRgn1); + SetClip(tkMacOSXtmpRgn1); + SetEmptyRgn(tkMacOSXtmpRgn1); if (!tkPictureIsOpen) { OffsetRgn(clipRgn, -xOffset, -yOffset); } @@ -243,8 +245,11 @@ XCopyArea( CopyBits(srcBit, dstBit, srcPtr, dstPtr, tmode, NULL); RGBForeColor(&origForeColor); RGBBackColor(&origBackColor); - SetClip(tmpRgn2); - SetGWorld(saveWorld, saveDevice); + SetClip(tkMacOSXtmpRgn2); + SetEmptyRgn(tkMacOSXtmpRgn2); + if (portChanged) { + QDSwapPort(savePort, NULL); + } } /* @@ -252,45 +257,37 @@ XCopyArea( * * XCopyPlane -- * - * Copies a bitmap from a source drawable to a destination - * drawable. The plane argument specifies which bit plane of - * the source contains the bitmap. Note that this implementation - * ignores the gc->function. + * Copies a bitmap from a source drawable to a destination + * drawable. The plane argument specifies which bit plane of + * the source contains the bitmap. Note that this implementation + * ignores the gc->function. * * Results: - * None. + * None. * * Side effects: - * Changes the destination drawable. + * Changes the destination drawable. * *---------------------------------------------------------------------- */ void XCopyPlane( - Display* display, /* Display. */ - Drawable src, /* Source drawable. */ - Drawable dst, /* Destination drawable. */ - GC gc, /* The GC to use. */ - int src_x, /* X, Y, width & height */ - int src_y, /* define the source rect. */ - unsigned int width, - unsigned int height, - int dest_x, /* X & Y on dest where we will copy. */ - int dest_y, - unsigned long plane) /* Which plane to copy. */ + Display *display, /* Display. */ + Drawable src, /* Source drawable. */ + Drawable dst, /* Destination drawable. */ + GC gc, /* The GC to use. */ + int src_x, int src_y, /* X, Y, width & height define the source + * rect. */ + unsigned int width, unsigned int height, + int dest_x, int dest_y, /* X & Y on dest where we will copy. */ + unsigned long plane) /* Which plane to copy. */ { - Rect srcRect, dstRect; - Rect * srcPtr, * dstPtr; - const BitMap * srcBit; - const BitMap * dstBit; - const BitMap * mskBit; - MacDrawable *srcDraw = (MacDrawable *) src; - MacDrawable *dstDraw = (MacDrawable *) dst; - GWorldPtr srcPort, dstPort, mskPort; - CGrafPtr saveWorld; - GDHandle saveDevice; - RGBColor macColor; + Rect srcRect, dstRect, *srcPtr, *dstPtr; + const BitMap *srcBit, *dstBit, *mskBit; + MacDrawable *srcDraw = (MacDrawable *) src, *dstDraw = (MacDrawable *) dst; + CGrafPtr srcPort, dstPort, mskPort, savePort; + Boolean portChanged; TkpClipMask *clipPtr = (TkpClipMask *) gc->clip_mask; short tmode; @@ -298,8 +295,7 @@ XCopyPlane( dstPort = TkMacOSXGetDrawablePort(dst); display->request++; - GetGWorld(&saveWorld, &saveDevice); - SetGWorld(dstPort, NULL); + portChanged = QDSwapPort(dstPort, &savePort); TkMacOSXSetUpClippingRgn(dst); srcBit = GetPortBitMapForCopyBits(srcPort); @@ -314,7 +310,7 @@ XCopyPlane( * When rendering into a picture, after a call to "OpenCPicture" * the clipping is seriously WRONG and also INCONSISTENT with the * clipping for color bitmaps. - * To circumvent this problem, we clip to the whole window + * To circumvent this problem, we clip to the whole window */ Rect clpRect; @@ -331,24 +327,21 @@ XCopyPlane( tmode = srcOr; tmode = srcCopy + transparent; - if (TkSetMacColor(gc->foreground, &macColor) == true) { - RGBForeColor(&macColor); - } + TkMacOSXSetColorInPort(gc->foreground, 1, NULL); if (clipPtr == NULL || clipPtr->type == TKP_CLIP_REGION) { /* * Case 1: opaque bitmaps. */ - TkSetMacColor(gc->background, &macColor); - RGBBackColor(&macColor); + TkMacOSXSetColorInPort(gc->background, 0, NULL); tmode = srcCopy; CopyBits(srcBit, dstBit, srcPtr, dstPtr, tmode, NULL); } else if (clipPtr->type == TKP_CLIP_PIXMAP) { if (clipPtr->value.pixmap == src) { PixMapHandle pm; /* - * Case 2: transparent bitmaps. If it's color we ignore + * Case 2: transparent bitmaps. If it's color we ignore * the forecolor. */ @@ -371,8 +364,9 @@ XCopyPlane( srcPtr, srcPtr, dstPtr, tmode, NULL); } } - - SetGWorld(saveWorld, saveDevice); + if (portChanged) { + QDSwapPort(savePort, NULL); + } } /* @@ -380,14 +374,14 @@ XCopyPlane( * * TkPutImage -- * - * Copies a subimage from an in-memory image to a rectangle of - * of the specified drawable. + * Copies a subimage from an in-memory image to a rectangle of + * of the specified drawable. * * Results: - * None. + * None. * * Side effects: - * Draws the image on the specified drawable. + * Draws the image on the specified drawable. * *---------------------------------------------------------------------- */ @@ -407,9 +401,8 @@ TkPutImage( unsigned int width, /* Same width & height for both */ unsigned int height) /* distination and source. */ { - CGrafPtr saveWorld; - GDHandle saveDevice; - GWorldPtr destPort; + CGrafPtr destPort, savePort; + Boolean portChanged; const BitMap * destBits; MacDrawable *dstDraw = (MacDrawable *) d; int i, j; @@ -420,9 +413,8 @@ TkPutImage( int slices, sliceRowBytes, lastSliceRowBytes, sliceWidth, lastSliceWidth; display->request++; - GetGWorld(&saveWorld, &saveDevice); destPort = TkMacOSXGetDrawablePort(d); - SetGWorld(destPort, NULL); + portChanged = QDSwapPort(destPort, &savePort); destBits = GetPortBitMapForCopyBits(destPort); TkMacOSXSetUpClippingRgn(d); @@ -433,10 +425,11 @@ TkPutImage( * When rendering into a picture, after a call to "OpenCPicture" * the clipping is seriously WRONG and also INCONSISTENT with the * clipping for single plane bitmaps. - * To circumvent this problem, we clip to the whole window + * To circumvent this problem, we clip to the whole window */ Rect clpRect; + GetPortBounds(destPort,&clpRect); ClipRect(&clpRect); destPtr = srcPtr; @@ -447,14 +440,17 @@ TkPutImage( } if (image->obdata) { - /* Image from XGetImage, copy from containing GWorld directly */ - GWorldPtr srcPort = TkMacOSXGetDrawablePort((Drawable)image->obdata); - CopyBits(GetPortBitMapForCopyBits(srcPort), - destBits, srcPtr, destPtr, srcCopy, NULL); + /* + * Image from XGetImage, copy from containing GWorld directly. + */ + + CopyBits(GetPortBitMapForCopyBits(TkMacOSXGetDrawablePort((Drawable) + image->obdata)), destBits, srcPtr, destPtr, srcCopy, NULL); } else if (image->depth == 1) { /* * BW image */ + const int maxRowBytes = 0x3ffe; BitMap bitmap; int odd; @@ -487,7 +483,7 @@ TkPutImage( oldPtr = dataPtr; odd = sliceRowBytes % 2; if (!newData) { - newData = (char *) ckalloc(image->height * (sliceRowBytes+odd)); + newData = ckalloc(image->height * (sliceRowBytes+odd)); } newPtr = newData; for (i = 0; i < image->height; i++) { @@ -512,6 +508,7 @@ TkPutImage( /* * Color image */ + const int maxRowBytes = 0x3ffc; PixMap pixmap; @@ -519,7 +516,7 @@ TkPutImage( pixmap.bounds.top = 0; pixmap.bounds.bottom = (short) image->height; pixmap.pixelType = RGBDirect; - pixmap.pmVersion = baseAddr32; /* 32bit clean */ + pixmap.pmVersion = baseAddr32; /* 32bit clean */ pixmap.packType = 0; pixmap.packSize = 0; pixmap.hRes = 0x00480000; @@ -580,8 +577,9 @@ TkPutImage( if (newData != NULL) { ckfree(newData); } - - SetGWorld(saveWorld, saveDevice); + if (portChanged) { + QDSwapPort(savePort, NULL); + } } /* @@ -589,74 +587,62 @@ TkPutImage( * * XDrawLines -- * - * Draw connected lines. + * Draw connected lines. * * Results: - * None. + * None. * * Side effects: - * Renders a series of connected lines. + * Renders a series of connected lines. * *---------------------------------------------------------------------- */ void XDrawLines( - Display* display, /* Display. */ + Display *display, /* Display. */ Drawable d, /* Draw on this. */ GC gc, /* Use this GC. */ - XPoint* points, /* Array of points. */ + XPoint *points, /* Array of points. */ int npoints, /* Number of points. */ int mode) /* Line drawing mode. */ { MacDrawable *macWin = (MacDrawable *) d; - CGrafPtr saveWorld; - GWorldPtr destPort; - GDHandle saveDevice; + TkMacOSXDrawingContext dc; int i, lw = gc->line_width; if (npoints < 2) { return; /* TODO: generate BadValue error. */ } - destPort = TkMacOSXGetDrawablePort(d); display->request++; - GetGWorld(&saveWorld, &saveDevice); - SetGWorld(destPort, NULL); - TkMacOSXSetUpClippingRgn(d); - - if (useCGDrawing) { - CGContextRef outContext; - float prevx, prevy; - float o = (lw % 2) ? .5 : 0; + if (TkMacOSXSetupDrawingContext(d, gc, useCGDrawing, &dc)) { + double prevx, prevy; + double o = (lw % 2) ? .5 : 0; - TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); - CGContextBeginPath(outContext); + CGContextBeginPath(dc.context); prevx = macWin->xOff + points[0].x + o; prevy = macWin->yOff + points[0].y + o; - CGContextMoveToPoint(outContext, prevx, prevy); + CGContextMoveToPoint(dc.context, prevx, prevy); for (i = 1; i < npoints; i++) { if (mode == CoordModeOrigin) { - CGContextAddLineToPoint(outContext, + CGContextAddLineToPoint(dc.context, macWin->xOff + points[i].x + o, macWin->yOff + points[i].y + o); } else { prevx += points[i].x; prevy += points[i].y; - CGContextAddLineToPoint(outContext, prevx, prevy); + CGContextAddLineToPoint(dc.context, prevx, prevy); } } - CGContextStrokePath(outContext); - TkMacOSXReleaseCGContext(macWin, destPort, &outContext); + CGContextStrokePath(dc.context); } else { int o = -lw/2; - TkMacOSXSetUpGraphicsPort(gc, destPort); - ShowPen(); - PenPixPat(gPenPat); /* This is broken for fat lines, it is not possible to correctly * imitate X11 drawing of oblique fat lines with QD line drawing, * we should draw a filled polygon instead. */ + MoveTo((short) (macWin->xOff + points[0].x + o), (short) (macWin->yOff + points[0].y + o)); for (i = 1; i < npoints; i++) { @@ -667,10 +653,8 @@ XDrawLines( Line((short) points[i].x, (short) points[i].y); } } - HidePen(); } - - SetGWorld(saveWorld, saveDevice); + TkMacOSXRestoreDrawingContext(&dc); } /* @@ -678,71 +662,58 @@ XDrawLines( * * XDrawSegments -- * - * Draw unconnected lines. + * Draw unconnected lines. * * Results: - * None. + * None. * * Side effects: - * Renders a series of unconnected lines. + * Renders a series of unconnected lines. * *---------------------------------------------------------------------- */ -void XDrawSegments( +void +XDrawSegments( Display *display, - Drawable d, + Drawable d, GC gc, XSegment *segments, - int nsegments) + int nsegments) { MacDrawable *macWin = (MacDrawable *) d; - CGrafPtr saveWorld; - GWorldPtr destPort; - GDHandle saveDevice; + TkMacOSXDrawingContext dc; int i, lw = gc->line_width; - destPort = TkMacOSXGetDrawablePort(d); display->request++; - GetGWorld(&saveWorld, &saveDevice); - SetGWorld(destPort, NULL); - TkMacOSXSetUpClippingRgn(d); + if (TkMacOSXSetupDrawingContext(d, gc, useCGDrawing, &dc)) { + double o = (lw % 2) ? .5 : 0; - if (useCGDrawing) { - CGContextRef outContext; - float o = (lw % 2) ? .5 : 0; - - TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); for (i = 0; i < nsegments; i++) { - CGContextBeginPath(outContext); - CGContextMoveToPoint(outContext, + CGContextBeginPath(dc.context); + CGContextMoveToPoint(dc.context, macWin->xOff + segments[i].x1 + o, macWin->yOff + segments[i].y1 + o); - CGContextAddLineToPoint(outContext, + CGContextAddLineToPoint(dc.context, macWin->xOff + segments[i].x2 + o, macWin->yOff + segments[i].y2 + o); - CGContextStrokePath(outContext); + CGContextStrokePath(dc.context); } - TkMacOSXReleaseCGContext(macWin, destPort, &outContext); } else { int o = -lw/2; - TkMacOSXSetUpGraphicsPort(gc, destPort); - ShowPen(); - PenPixPat(gPenPat); /* This is broken for fat lines, it is not possible to correctly * imitate X11 drawing of oblique fat lines with QD line drawing, * we should draw a filled polygon instead. */ + for (i = 0; i < nsegments; i++) { MoveTo((short) (macWin->xOff + segments[i].x1 + o), (short) (macWin->yOff + segments[i].y1 + o)); LineTo((short) (macWin->xOff + segments[i].x2 + o), (short) (macWin->yOff + segments[i].y2 + o)); } - HidePen(); } - - SetGWorld(saveWorld, saveDevice); + TkMacOSXRestoreDrawingContext(&dc); } /* @@ -750,13 +721,13 @@ void XDrawSegments( * * XFillPolygon -- * - * Draws a filled polygon. + * Draws a filled polygon. * * Results: - * None. + * None. * * Side effects: - * Draws a filled polygon on the specified drawable. + * Draws a filled polygon on the specified drawable. * *---------------------------------------------------------------------- */ @@ -772,45 +743,33 @@ XFillPolygon( int mode) /* Drawing mode. */ { MacDrawable *macWin = (MacDrawable *) d; - CGrafPtr saveWorld; - GDHandle saveDevice; - GWorldPtr destPort; + TkMacOSXDrawingContext dc; int i; - destPort = TkMacOSXGetDrawablePort(d); display->request++; - GetGWorld(&saveWorld, &saveDevice); - SetGWorld(destPort, NULL); - TkMacOSXSetUpClippingRgn(d); - - if (useCGDrawing) { - CGContextRef outContext; - float prevx, prevy; - float o = (gc->line_width % 2) ? .5 : 0; + if (TkMacOSXSetupDrawingContext(d, gc, useCGDrawing, &dc)) { + double prevx, prevy; + double o = (gc->line_width % 2) ? .5 : 0; - TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); - CGContextBeginPath(outContext); + CGContextBeginPath(dc.context); prevx = macWin->xOff + points[0].x + o; prevy = macWin->yOff + points[0].y + o; - CGContextMoveToPoint(outContext, prevx, prevy); + CGContextMoveToPoint(dc.context, prevx, prevy); for (i = 1; i < npoints; i++) { if (mode == CoordModeOrigin) { - CGContextAddLineToPoint(outContext, + CGContextAddLineToPoint(dc.context, macWin->xOff + points[i].x + o, macWin->yOff + points[i].y + o); } else { prevx += points[i].x; prevy += points[i].y; - CGContextAddLineToPoint(outContext, prevx, prevy); + CGContextAddLineToPoint(dc.context, prevx, prevy); } } - CGContextEOFillPath(outContext); - TkMacOSXReleaseCGContext(macWin, destPort, &outContext); + CGContextEOFillPath(dc.context); } else { PolyHandle polygon; - TkMacOSXSetUpGraphicsPort(gc, destPort); - PenNormal(); polygon = OpenPoly(); MoveTo((short) (macWin->xOff + points[0].x), (short) (macWin->yOff + points[0].y)); @@ -823,11 +782,10 @@ XFillPolygon( } } ClosePoly(); - FillCPoly(polygon, gPenPat); + FillCPoly(polygon, dc.penPat); KillPoly(polygon); } - - SetGWorld(saveWorld, saveDevice); + TkMacOSXRestoreDrawingContext(&dc); } /* @@ -835,71 +793,55 @@ XFillPolygon( * * XDrawRectangle -- * - * Draws a rectangle. + * Draws a rectangle. * * Results: - * None. + * None. * * Side effects: - * Draws a rectangle on the specified drawable. + * Draws a rectangle on the specified drawable. * *---------------------------------------------------------------------- */ void XDrawRectangle( - Display* display, /* Display. */ - Drawable d, /* Draw on this. */ - GC gc, /* Use this GC. */ - int x, /* Upper left corner. */ - int y, - unsigned int width, /* Width & height of rect. */ + Display *display, /* Display. */ + Drawable d, /* Draw on this. */ + GC gc, /* Use this GC. */ + int x, int y, /* Upper left corner. */ + unsigned int width, /* Width & height of rect. */ unsigned int height) { MacDrawable *macWin = (MacDrawable *) d; - CGrafPtr saveWorld; - GDHandle saveDevice; - GWorldPtr destPort; + TkMacOSXDrawingContext dc; int lw = gc->line_width; if (width == 0 || height == 0) { return; } - destPort = TkMacOSXGetDrawablePort(d); display->request++; - GetGWorld(&saveWorld, &saveDevice); - SetGWorld(destPort, NULL); - TkMacOSXSetUpClippingRgn(d); - - if (useCGDrawing) { - CGContextRef outContext; + if (TkMacOSXSetupDrawingContext(d, gc, useCGDrawing, &dc)) { CGRect rect; - float o = (lw % 2) ? .5 : 0; + double o = (lw % 2) ? .5 : 0; - TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); rect = CGRectMake( macWin->xOff + x + o, macWin->yOff + y + o, width, height); - CGContextStrokeRect(outContext, rect); - TkMacOSXReleaseCGContext(macWin, destPort, &outContext); + CGContextStrokeRect(dc.context, rect); } else { Rect theRect; int o = -lw/2; - TkMacOSXSetUpGraphicsPort(gc, destPort); - ShowPen(); - PenPixPat(gPenPat); - theRect.left = (short) (macWin->xOff + x + o); - theRect.top = (short) (macWin->yOff + y + o); - theRect.right = (short) (theRect.left + width + lw); + theRect.left = (short) (macWin->xOff + x + o); + theRect.top = (short) (macWin->yOff + y + o); + theRect.right = (short) (theRect.left + width + lw); theRect.bottom = (short) (theRect.top + height + lw); FrameRect(&theRect); - HidePen(); } - - SetGWorld(saveWorld, saveDevice); + TkMacOSXRestoreDrawingContext(&dc); } #ifdef TK_MACOSXDRAW_UNUSED @@ -908,27 +850,27 @@ XDrawRectangle( * * XDrawRectangles -- * - * Draws the outlines of the specified rectangles as if a - * five-point PolyLine protocol request were specified for each - * rectangle: + * Draws the outlines of the specified rectangles as if a + * five-point PolyLine protocol request were specified for each + * rectangle: * - * [x,y] [x+width,y] [x+width,y+height] [x,y+height] - * [x,y] + * [x,y] [x+width,y] [x+width,y+height] [x,y+height] [x,y] * - * For the specified rectangles, these functions do not draw a - * pixel more than once. XDrawRectangles draws the rectangles in - * the order listed in the array. If rectangles intersect, the - * intersecting pixels are drawn multiple times. Draws a - * rectangle. + * For the specified rectangles, these functions do not draw a + * pixel more than once. XDrawRectangles draws the rectangles in + * the order listed in the array. If rectangles intersect, the + * intersecting pixels are drawn multiple times. Draws a + * rectangle. * * Results: - * None. + * None. * * Side effects: - * Draws rectangles on the specified drawable. + * Draws rectangles on the specified drawable. * *---------------------------------------------------------------------- */ + void XDrawRectangles( Display *display, @@ -938,24 +880,15 @@ XDrawRectangles( int nRects) { MacDrawable *macWin = (MacDrawable *) drawable; - CGrafPtr saveWorld; - GDHandle saveDevice; - GWorldPtr destPort; + TkMacOSXDrawingContext dc; XRectangle * rectPtr; int i, lw = gc->line_width; - destPort = TkMacOSXGetDrawablePort(drawable); display->request++; - GetGWorld(&saveWorld, &saveDevice); - SetGWorld(destPort, NULL); - TkMacOSXSetUpClippingRgn(drawable); - - if (useCGDrawing) { - CGContextRef outContext; + if (TkMacOSXSetupDrawingContext(d, gc, useCGDrawing, &dc)) { CGRect rect; - float o = (lw % 2) ? .5 : 0; + double o = (lw % 2) ? .5 : 0; - TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); for (i = 0, rectPtr = rectArr; i < nRects; i++, rectPtr++) { if (rectPtr->width == 0 || rectPtr->height == 0) { continue; @@ -964,16 +897,12 @@ XDrawRectangles( macWin->xOff + rectPtr->x + o, macWin->yOff + rectPtr->y + o, rectPtr->width, rectPtr->height); - CGContextStrokeRect(outContext, rect); + CGContextStrokeRect(dc.context, rect); } - TkMacOSXReleaseCGContext(macWin, destPort, &outContext); } else { Rect theRect; int o = -lw/2; - TkMacOSXSetUpGraphicsPort(gc, destPort); - ShowPen(); - PenPixPat(gPenPat); for (i = 0, rectPtr = rectArr; i < nRects;i++, rectPtr++) { theRect.left = (short) (macWin->xOff + rectPtr->x + o); theRect.top = (short) (macWin->yOff + rectPtr->y + o); @@ -981,10 +910,8 @@ XDrawRectangles( theRect.bottom = (short) (theRect.top + rectPtr->height + lw); FrameRect(&theRect); } - HidePen(); } - - SetGWorld(saveWorld, saveDevice); + TkMacOSXRestoreDrawingContext(&dc); } #endif @@ -993,42 +920,34 @@ XDrawRectangles( * * XFillRectangles -- * - * Fill multiple rectangular areas in the given drawable. + * Fill multiple rectangular areas in the given drawable. * * Results: - * None. + * None. * * Side effects: - * Draws onto the specified drawable. + * Draws onto the specified drawable. * *---------------------------------------------------------------------- */ + void XFillRectangles( - Display* display, /* Display. */ - Drawable d, /* Draw on this. */ - GC gc, /* Use this GC. */ - XRectangle *rectangles, /* Rectangle array. */ - int n_rectangles) /* Number of rectangles. */ + Display* display, /* Display. */ + Drawable d, /* Draw on this. */ + GC gc, /* Use this GC. */ + XRectangle *rectangles, /* Rectangle array. */ + int n_rectangles) /* Number of rectangles. */ { MacDrawable *macWin = (MacDrawable *) d; - CGrafPtr saveWorld; - GDHandle saveDevice; - GWorldPtr destPort; + TkMacOSXDrawingContext dc; XRectangle * rectPtr; int i; - destPort = TkMacOSXGetDrawablePort(d); display->request++; - GetGWorld(&saveWorld, &saveDevice); - SetGWorld(destPort, NULL); - TkMacOSXSetUpClippingRgn(d); - - if (useCGDrawing) { - CGContextRef outContext; + if (TkMacOSXSetupDrawingContext(d, gc, useCGDrawing, &dc)) { CGRect rect; - TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); for (i = 0, rectPtr = rectangles; i < n_rectangles; i++, rectPtr++) { if (rectPtr->width == 0 || rectPtr->height == 0) { continue; @@ -1037,23 +956,20 @@ XFillRectangles( macWin->xOff + rectPtr->x, macWin->yOff + rectPtr->y, rectPtr->width, rectPtr->height); - CGContextFillRect(outContext, rect); + CGContextFillRect(dc.context, rect); } - TkMacOSXReleaseCGContext(macWin, destPort, &outContext); } else { Rect theRect; - TkMacOSXSetUpGraphicsPort(gc, destPort); for (i = 0, rectPtr = rectangles; i < n_rectangles; i++, rectPtr++) { theRect.left = (short) (macWin->xOff + rectPtr->x); theRect.top = (short) (macWin->yOff + rectPtr->y); theRect.right = (short) (theRect.left + rectPtr->width); theRect.bottom = (short) (theRect.top + rectPtr->height); - FillCRect(&theRect, gPenPat); + FillCRect(&theRect, dc.penPat); } } - - SetGWorld(saveWorld, saveDevice); + TkMacOSXRestoreDrawingContext(&dc); } /* @@ -1061,98 +977,85 @@ XFillRectangles( * * XDrawArc -- * - * Draw an arc. + * Draw an arc. * * Results: - * None. + * None. * * Side effects: - * Draws an arc on the specified drawable. + * Draws an arc on the specified drawable. * *---------------------------------------------------------------------- */ void XDrawArc( - Display* display, /* Display. */ - Drawable d, /* Draw on this. */ - GC gc, /* Use this GC. */ - int x, /* Upper left of */ - int y, /* bounding rect. */ - unsigned int width, /* Width & height. */ + Display* display, /* Display. */ + Drawable d, /* Draw on this. */ + GC gc, /* Use this GC. */ + int x, int y, /* Upper left of bounding rect. */ + unsigned int width, /* Width & height. */ unsigned int height, - int angle1, /* Staring angle of arc. */ - int angle2) /* Extent of arc. */ + int angle1, /* Staring angle of arc. */ + int angle2) /* Extent of arc. */ { MacDrawable *macWin = (MacDrawable *) d; - CGrafPtr saveWorld; - GDHandle saveDevice; - GWorldPtr destPort; + TkMacOSXDrawingContext dc; int lw = gc->line_width; if (width == 0 || height == 0 || angle2 == 0) { return; } - destPort = TkMacOSXGetDrawablePort(d); display->request++; - GetGWorld(&saveWorld, &saveDevice); - SetGWorld(destPort, NULL); - TkMacOSXSetUpClippingRgn(d); - - if (useCGDrawing) { - CGContextRef outContext; + if (TkMacOSXSetupDrawingContext(d, gc, useCGDrawing, &dc)) { CGRect rect; - float o = (lw % 2) ? .5 : 0; + double o = (lw % 2) ? .5 : 0; - TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); rect = CGRectMake( macWin->xOff + x + o, macWin->yOff + y + o, width, height); #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 - if (angle1 == 0 && angle2 == 23040 && - CGContextStrokeEllipseInRect != NULL) { - CGContextStrokeEllipseInRect(outContext, rect); + if (angle1 == 0 && angle2 == 23040 +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 + && CGContextStrokeEllipseInRect != NULL +#endif + ) { + CGContextStrokeEllipseInRect(dc.context, rect); } else #endif { CGMutablePathRef p = CGPathCreateMutable(); CGAffineTransform t = CGAffineTransformIdentity; CGPoint c = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect)); - float w = CGRectGetWidth(rect); + double w = CGRectGetWidth(rect); if (width != height) { - t = CGAffineTransformMakeScale(1, CGRectGetHeight(rect)/w); + t = CGAffineTransformMakeScale(1.0, CGRectGetHeight(rect)/w); c = CGPointApplyAffineTransform(c, CGAffineTransformInvert(t)); } CGPathAddArc(p, &t, c.x, c.y, w/2, radians(-angle1/64.0), radians(-(angle1 + angle2)/64.0), angle2 > 0); - CGContextAddPath(outContext, p); + CGContextAddPath(dc.context, p); CGPathRelease(p); - CGContextStrokePath(outContext); + CGContextStrokePath(dc.context); } - TkMacOSXReleaseCGContext(macWin, destPort, &outContext); } else { Rect theRect; short start, extent; int o = -lw/2; - TkMacOSXSetUpGraphicsPort(gc, destPort); - ShowPen(); - PenPixPat(gPenPat); - theRect.left = (short) (macWin->xOff + x + o); - theRect.top = (short) (macWin->yOff + y + o); - theRect.right = (short) (theRect.left + width + lw); + theRect.left = (short) (macWin->xOff + x + o); + theRect.top = (short) (macWin->yOff + y + o); + theRect.right = (short) (theRect.left + width + lw); theRect.bottom = (short) (theRect.top + height + lw); - start = (short) (90 - (angle1/64)); + start = (short) (90 - (angle1/64)); extent = (short) (-(angle2/64)); FrameArc(&theRect, start, extent); - HidePen(); } - - SetGWorld(saveWorld, saveDevice); + TkMacOSXRestoreDrawingContext(&dc); } #ifdef TK_MACOSXDRAW_UNUSED @@ -1161,23 +1064,24 @@ XDrawArc( * * XDrawArcs -- * - * Draws multiple circular or elliptical arcs. Each arc is - * specified by a rectangle and two angles. The center of the - * circle or ellipse is the center of the rect- angle, and the - * major and minor axes are specified by the width and height. - * Positive angles indicate counterclock- wise motion, and - * negative angles indicate clockwise motion. If the magnitude - * of angle2 is greater than 360 degrees, XDrawArcs truncates it - * to 360 degrees. + * Draws multiple circular or elliptical arcs. Each arc is + * specified by a rectangle and two angles. The center of the + * circle or ellipse is the center of the rect- angle, and the + * major and minor axes are specified by the width and height. + * Positive angles indicate counterclock- wise motion, and + * negative angles indicate clockwise motion. If the magnitude + * of angle2 is greater than 360 degrees, XDrawArcs truncates it + * to 360 degrees. * * Results: - * None. + * None. * * Side effects: - * Draws an arc for each array element on the specified drawable. + * Draws an arc for each array element on the specified drawable. * *---------------------------------------------------------------------- */ + void XDrawArcs( Display *display, @@ -1188,24 +1092,15 @@ XDrawArcs( { MacDrawable *macWin = (MacDrawable *) d; - CGrafPtr saveWorld; - GDHandle saveDevice; - GWorldPtr destPort; - XArc * arcPtr; + TkMacOSXDrawingContext dc; + XArc *arcPtr; int i, lw = gc->line_width; - destPort = TkMacOSXGetDrawablePort(d); display->request++; - GetGWorld(&saveWorld, &saveDevice); - SetGWorld(destPort, NULL); - TkMacOSXSetUpClippingRgn(d); - - if (useCGDrawing) { - CGContextRef outContext; + if (TkMacOSXSetupDrawingContext(d, gc, useCGDrawing, &dc)) { CGRect rect; - float o = (lw % 2) ? .5 : 0; + double o = (lw % 2) ? .5 : 0; - TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); for (i=0, arcPtr = arcArr; i < nArcs; i++, arcPtr++) { if (arcPtr->width == 0 || arcPtr->height == 0 || arcPtr->angle2 == 0) { @@ -1217,41 +1112,40 @@ XDrawArcs( arcPtr->width, arcPtr->height); #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 - if (arcPtr->angle1 == 0 && arcPtr->angle2 == 23040 && - CGContextStrokeEllipseInRect != NULL) { - CGContextStrokeEllipseInRect(outContext, rect); + if (arcPtr->angle1 == 0 && arcPtr->angle2 == 23040 +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 + && CGContextStrokeEllipseInRect != NULL +#endif + ) { + CGContextStrokeEllipseInRect(dc.context, rect); } else #endif { CGMutablePathRef p = CGPathCreateMutable(); CGAffineTransform t = CGAffineTransformIdentity; CGPoint c = CGPointMake(CGRectGetMidX(rect), - CGRectGetMidY(rect)); - float w = CGRectGetWidth(rect); + CGRectGetMidY(rect)); + double w = CGRectGetWidth(rect); if (arcPtr->width != arcPtr->height) { t = CGAffineTransformMakeScale(1, CGRectGetHeight(rect)/w); c = CGPointApplyAffineTransform(c, - CGAffineTransformInvert(t)); + CGAffineTransformInvert(t)); } CGPathAddArc(p, &t, c.x, c.y, w/2, radians(-arcPtr->angle1/64.0), radians(-(arcPtr->angle1 + arcPtr->angle2)/64.0), arcPtr->angle2 > 0); - CGContextAddPath(outContext, p); + CGContextAddPath(dc.context, p); CGPathRelease(p); - CGContextStrokePath(outContext); + CGContextStrokePath(dc.context); } } - TkMacOSXReleaseCGContext(macWin, destPort, &outContext); } else { Rect theRect; short start, extent; int o = -lw/2; - TkMacOSXSetUpGraphicsPort(gc, destPort); - ShowPen(); - PenPixPat(gPenPat); for (i = 0, arcPtr = arcArr;i < nArcs;i++, arcPtr++) { theRect.left = (short) (macWin->xOff + arcPtr->x + o); theRect.top = (short) (macWin->yOff + arcPtr->y + o); @@ -1261,10 +1155,8 @@ XDrawArcs( extent = (short) (-(arcPtr->angle2/64)); FrameArc(&theRect, start, extent); } - HidePen(); } - - SetGWorld(saveWorld, saveDevice); + TkMacOSXRestoreDrawingContext(&dc); } #endif @@ -1273,71 +1165,64 @@ XDrawArcs( * * XFillArc -- * - * Draw a filled arc. + * Draw a filled arc. * * Results: - * None. + * None. * * Side effects: - * Draws a filled arc on the specified drawable. + * Draws a filled arc on the specified drawable. * *---------------------------------------------------------------------- */ void XFillArc( - Display* display, /* Display. */ - Drawable d, /* Draw on this. */ - GC gc, /* Use this GC. */ - int x, /* Upper left of */ - int y, /* bounding rect. */ - unsigned int width, /* Width & height. */ + Display* display, /* Display. */ + Drawable d, /* Draw on this. */ + GC gc, /* Use this GC. */ + int x, int y, /* Upper left of bounding rect. */ + unsigned int width, /* Width & height. */ unsigned int height, - int angle1, /* Staring angle of arc. */ - int angle2) /* Extent of arc. */ + int angle1, /* Staring angle of arc. */ + int angle2) /* Extent of arc. */ { MacDrawable *macWin = (MacDrawable *) d; - CGrafPtr saveWorld; - GDHandle saveDevice; - GWorldPtr destPort; + TkMacOSXDrawingContext dc; int lw = gc->line_width; if (width == 0 || height == 0 || angle2 == 0) { return; } - destPort = TkMacOSXGetDrawablePort(d); display->request++; - GetGWorld(&saveWorld, &saveDevice); - SetGWorld(destPort, NULL); - TkMacOSXSetUpClippingRgn(d); - - if (useCGDrawing) { - CGContextRef outContext; + if (TkMacOSXSetupDrawingContext(d, gc, useCGDrawing, &dc)) { CGRect rect; - float o = (lw % 2) ? .5 : 0, u = 0; + double o = (lw % 2) ? .5 : 0, u = 0; if (notAA(lw)) { o += NON_AA_CG_OFFSET/2; u += NON_AA_CG_OFFSET; } - TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); rect = CGRectMake( macWin->xOff + x + o, macWin->yOff + y + o, width - u, height - u); #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 - if (angle1 == 0 && angle2 == 23040 && - CGContextFillEllipseInRect != NULL) { - CGContextFillEllipseInRect(outContext, rect); + if (angle1 == 0 && angle2 == 23040 +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 + && CGContextFillEllipseInRect != NULL +#endif + ) { + CGContextFillEllipseInRect(dc.context, rect); } else #endif { CGMutablePathRef p = CGPathCreateMutable(); CGAffineTransform t = CGAffineTransformIdentity; CGPoint c = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect)); - float w = CGRectGetWidth(rect); + double w = CGRectGetWidth(rect); if (width != height) { t = CGAffineTransformMakeScale(1, CGRectGetHeight(rect)/w); @@ -1349,11 +1234,10 @@ XFillArc( CGPathAddArc(p, &t, c.x, c.y, w/2, radians(-angle1/64.0), radians(-(angle1 + angle2)/64.0), angle2 > 0); CGPathCloseSubpath(p); - CGContextAddPath(outContext, p); + CGContextAddPath(dc.context, p); CGPathRelease(p); - CGContextFillPath(outContext); + CGContextFillPath(dc.context); } - TkMacOSXReleaseCGContext(macWin, destPort, &outContext); } else { Rect theRect; short start, extent; @@ -1363,10 +1247,9 @@ XFillArc( double boxWidth, boxHeight; double vertex[2], center1[2], center2[2]; - TkMacOSXSetUpGraphicsPort(gc, destPort); - theRect.left = (short) (macWin->xOff + x + o); - theRect.top = (short) (macWin->yOff + y + o); - theRect.right = (short) (theRect.left + width + lw); + theRect.left = (short) (macWin->xOff + x + o); + theRect.top = (short) (macWin->yOff + y + o); + theRect.right = (short) (theRect.left + width + lw); theRect.bottom = (short) (theRect.top + height + lw); start = (short) (90 - (angle1/64)); extent = (short) (-(angle2/64)); @@ -1392,19 +1275,14 @@ XFillArc( LineTo((short) (center1[0] + .5), (short) (center1[1] + .5)); LineTo((short) (center2[0] + .5), (short) (center2[1] + .5)); ClosePoly(); - ShowPen(); - FillCArc(&theRect, start, extent, gPenPat); - FillCPoly(polygon, gPenPat); - HidePen(); + FillCArc(&theRect, start, extent, dc.penPat); + FillCPoly(polygon, dc.penPat); KillPoly(polygon); } else { - ShowPen(); - FillCArc(&theRect, start, extent, gPenPat); - HidePen(); + FillCArc(&theRect, start, extent, dc.penPat); } } - - SetGWorld(saveWorld, saveDevice); + TkMacOSXRestoreDrawingContext(&dc); } #ifdef TK_MACOSXDRAW_UNUSED @@ -1413,16 +1291,17 @@ XFillArc( * * XFillArcs -- * - * Draw a filled arc. + * Draw a filled arc. * * Results: - * None. + * None. * * Side effects: - * Draws a filled arc for each array element on the specified drawable. + * Draws a filled arc for each array element on the specified drawable. * *---------------------------------------------------------------------- */ + void XFillArcs( Display *display, @@ -1432,28 +1311,19 @@ XFillArcs( int nArcs) { MacDrawable *macWin = (MacDrawable *) d; - CGrafPtr saveWorld; - GDHandle saveDevice; - GWorldPtr destPort; + TkMacOSXDrawingContext dc; XArc * arcPtr; int i, lw = gc->line_width; - destPort = TkMacOSXGetDrawablePort(d); display->request++; - GetGWorld(&saveWorld, &saveDevice); - SetGWorld(destPort, NULL); - TkMacOSXSetUpClippingRgn(d); - - if (useCGDrawing) { - CGContextRef outContext; + if (TkMacOSXSetupDrawingContext(d, gc, useCGDrawing, &dc)) { CGRect rect; - float o = (lw % 2) ? .5 : 0, u = 0; + double o = (lw % 2) ? .5 : 0, u = 0; if (notAA(lw)) { o += NON_AA_CG_OFFSET/2; u += NON_AA_CG_OFFSET; } - TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); for (i = 0, arcPtr = arcArr; i < nArcs; i++, arcPtr++) { if (arcPtr->width == 0 || arcPtr->height == 0 || arcPtr->angle2 == 0) { @@ -1465,22 +1335,25 @@ XFillArcs( arcPtr->width - u, arcPtr->height - u); #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1040 - if (arcPtr->angle1 == 0 && arcPtr->angle2 == 23040 && - CGContextFillEllipseInRect != NULL) { - CGContextFillEllipseInRect(outContext, rect); + if (arcPtr->angle1 == 0 && arcPtr->angle2 == 23040 +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1040 + && CGContextFillEllipseInRect != NULL +#endif + ) { + CGContextFillEllipseInRect(dc.context, rect); } else #endif { CGMutablePathRef p = CGPathCreateMutable(); CGAffineTransform t = CGAffineTransformIdentity; CGPoint c = CGPointMake(CGRectGetMidX(rect), - CGRectGetMidY(rect)); - float w = CGRectGetWidth(rect); + CGRectGetMidY(rect)); + double w = CGRectGetWidth(rect); if (arcPtr->width != arcPtr->height) { t = CGAffineTransformMakeScale(1, CGRectGetHeight(rect)/w); c = CGPointApplyAffineTransform(c, - CGAffineTransformInvert(t)); + CGAffineTransformInvert(t)); } if (gc->arc_mode == ArcPieSlice) { CGPathMoveToPoint(p, &t, c.x, c.y); @@ -1490,12 +1363,11 @@ XFillArcs( radians(-(arcPtr->angle1 + arcPtr->angle2)/64.0), arcPtr->angle2 > 0); CGPathCloseSubpath(p); - CGContextAddPath(outContext, p); + CGContextAddPath(dc.context, p); CGPathRelease(p); - CGContextFillPath(outContext); + CGContextFillPath(dc.context); } } - TkMacOSXReleaseCGContext(macWin, destPort, &outContext); } else { Rect theRect; short start, extent; @@ -1505,7 +1377,6 @@ XFillArcs( double boxWidth, boxHeight; double vertex[2], center1[2], center2[2]; - TkMacOSXSetUpGraphicsPort(gc, destPort); for (i = 0, arcPtr = arcArr;ixOff + arcPtr->x + o); theRect.top = (short) (macWin->yOff + arcPtr->y + o); @@ -1536,20 +1407,15 @@ XFillArcs( LineTo((short) (center1[0] + .5), (short) (center1[1] + .5)); LineTo((short) (center2[0] + .5), (short) (center2[1] + .5)); ClosePoly(); - ShowPen(); - FillCArc(&theRect, start, extent, gPenPat); - FillCPoly(polygon, gPenPat); - HidePen(); + FillCArc(&theRect, start, extent, dc.penPat); + FillCPoly(polygon, dc.penPat); KillPoly(polygon); } else { - ShowPen(); - FillCArc(&theRect, start, extent, gPenPat); - HidePen(); + FillCArc(&theRect, start, extent, dc.penPat); } } } - - SetGWorld(saveWorld, saveDevice); + TkMacOSXRestoreDrawingContext(&dc); } #endif @@ -1561,8 +1427,10 @@ XFillArcs( * *---------------------------------------------------------------------- */ + long -XMaxRequestSize(Display *display) +XMaxRequestSize( + Display *display) { return (SHRT_MAX / 4); } @@ -1573,51 +1441,45 @@ XMaxRequestSize(Display *display) * * TkScrollWindow -- * - * Scroll a rectangle of the specified window and accumulate - * a damage region. + * Scroll a rectangle of the specified window and accumulate + * a damage region. * * Results: - * Returns 0 if the scroll genereated no additional damage. - * Otherwise, sets the region that needs to be repainted after - * scrolling and returns 1. + * Returns 0 if the scroll genereated no additional damage. + * Otherwise, sets the region that needs to be repainted after + * scrolling and returns 1. * * Side effects: - * Scrolls the bits in the window. + * Scrolls the bits in the window. * *---------------------------------------------------------------------- */ int TkScrollWindow( - Tk_Window tkwin, /* The window to be scrolled. */ - GC gc, /* GC for window to be scrolled. */ - int x, /* Position rectangle to be scrolled. */ - int y, - int width, - int height, - int dx, /* Distance rectangle should be moved. */ - int dy, - TkRegion damageRgn) /* Region to accumulate damage in. */ + Tk_Window tkwin, /* The window to be scrolled. */ + GC gc, /* GC for window to be scrolled. */ + int x, int y, /* Position rectangle to be scrolled. */ + int width, int height, + int dx, int dy, /* Distance rectangle should be moved. */ + TkRegion damageRgn) /* Region to accumulate damage in. */ { MacDrawable *destDraw = (MacDrawable *) Tk_WindowId(tkwin); RgnHandle rgn = (RgnHandle) damageRgn; - CGrafPtr saveWorld; - GDHandle saveDevice; - GWorldPtr destPort; + CGrafPtr destPort, savePort; + Boolean portChanged; Rect srcRect, scrollRect; - RgnHandle visRgn, clipRgn; destPort = TkMacOSXGetDrawablePort(Tk_WindowId(tkwin)); - GetGWorld(&saveWorld, &saveDevice); - SetGWorld(destPort, NULL); + portChanged = QDSwapPort(destPort, &savePort); TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin)); /* * Due to the implementation below the behavior may be differnt - * than X in certain cases that should never occur in Tk. The + * than X in certain cases that should never occur in Tk. The * scrollRect is the source rect extended by the offset (the union - * of the source rect and the offset rect). Everything - * in the extended scrollRect is scrolled. On X, it's possible + * of the source rect and the offset rect). Everything + * in the extended scrollRect is scrolled. On X, it's possible * to "skip" over an area if the offset makes the source and * destination rects disjoint and non-aligned. */ @@ -1642,45 +1504,27 @@ TkScrollWindow( * Adjust clip region so that we don't copy any windows * that may overlap us. */ - visRgn = NewRgn(); - clipRgn = NewRgn(); + + TkMacOSXCheckTmpRgnEmpty(1); + TkMacOSXCheckTmpRgnEmpty(2); RectRgn(rgn, &srcRect); - GetPortVisibleRegion(destPort,visRgn); - DiffRgn(rgn, visRgn, rgn); + GetPortVisibleRegion(destPort,tkMacOSXtmpRgn1); + DiffRgn(rgn, tkMacOSXtmpRgn1, rgn); OffsetRgn(rgn, dx, dy); - GetPortClipRegion(destPort, clipRgn); - DiffRgn(clipRgn, rgn, clipRgn); - SetPortClipRegion(destPort, clipRgn); + GetPortClipRegion(destPort, tkMacOSXtmpRgn2); + DiffRgn(tkMacOSXtmpRgn2, rgn, tkMacOSXtmpRgn2); + SetPortClipRegion(destPort, tkMacOSXtmpRgn2); + SetEmptyRgn(tkMacOSXtmpRgn1); + SetEmptyRgn(tkMacOSXtmpRgn2); SetEmptyRgn(rgn); - /* - * When a menu is up, the Mac does not expect drawing to occur and - * does not clip out the menu. We have to do it ourselves. This - * is pretty gross. - */ - - if (tkUseMenuCascadeRgn == 1) { - Point scratch = {0, 0}; - MacDrawable *macDraw = (MacDrawable *) Tk_WindowId(tkwin); - - LocalToGlobal(&scratch); - CopyRgn(tkMenuCascadeRgn, rgn); - OffsetRgn(rgn, -scratch.h, -scratch.v); - DiffRgn(clipRgn, rgn, clipRgn); - SetPortClipRegion(destPort, clipRgn); - SetEmptyRgn(rgn); - macDraw->toplevel->flags |= TK_DRAWN_UNDER_MENU; - } - ScrollRect(&scrollRect, dx, dy, rgn); - - SetGWorld(saveWorld, saveDevice); - - DisposeRgn(clipRgn); - DisposeRgn(visRgn); + if (portChanged) { + QDSwapPort(savePort, NULL); + } /* - * Fortunantly, the region returned by ScrollRect is symanticlly - * the same as what we need to return in this function. If the + * Fortunately, the region returned by ScrollRect is semantically + * the same as what we need to return in this function. If the * region is empty we return zero to denote that no damage was * created. */ @@ -1696,220 +1540,300 @@ TkScrollWindow( * * TkMacOSXSetUpGraphicsPort -- * - * Set up the graphics port from the given GC. + * Set up the graphics port from the given GC. * * Results: - * None. + * None. * * Side effects: - * The current port is adjusted. + * The current port is adjusted. * *---------------------------------------------------------------------- */ void TkMacOSXSetUpGraphicsPort( - GC gc, - GWorldPtr destPort) /* GC to apply to current port. */ + GC gc, /* GC to apply to current port. */ + GWorldPtr destPort) { - RGBColor macColor; - - if (gPenPat == NULL) { - gPenPat = NewPixPat(); - } - - if (TkSetMacColor(gc->foreground, &macColor) == true) { - /* TODO: cache RGBPats for preformace - measure gains... */ - MakeRGBPat(gPenPat, &macColor); - } - PenNormal(); - if(gc->function == GXxor) { - PenMode(patXor); - } - if (gc->line_width > 1) { - PenSize(gc->line_width, gc->line_width); - } - if (gc->line_style != LineSolid) { - /* - * Here the dash pattern should be set in the drawing, - * environment, but I don't know how to do that for the Mac. - * - * p[] is an array of unsigned chars containing the dash list. - * A '\0' indicates the end of this list. - * - * Someone knows how to implement this? If you have a more - * complete implementation of SetUpGraphicsPort() for - * the Mac (or for Windows), please let me know. - * - * Jan Nijtmans - * CMG Arnhem, B.V. - * email: j.nijtmans@chello.nl (private) - * jan.nijtmans@cmg.nl (work) - * url: http://purl.oclc.org/net/nijtmans/ - * - * FIXME: - * This is not possible with QuickDraw line drawing. As of - * Tk 8.4.7 we have a complete set of drawing routines using - * CG, so there is no reason to support this here. - */ + if (gc) { + if (gPenPat == NULL) { + gPenPat = NewPixPat(); + } + TkMacOSXSetColorInPort(gc->foreground, 1, gPenPat); + PenPixPat(gPenPat); + if(gc->function == GXxor) { + PenMode(patXor); + } + if (gc->line_width > 1) { + PenSize(gc->line_width, gc->line_width); + } + if (gc->line_style != LineSolid) { + /* + * FIXME: + * Here the dash pattern should be set in the drawing environment. + * This is not possible with QuickDraw line drawing. + */ + } } } /* *---------------------------------------------------------------------- * - * TkMacOSXSetUpCGContext -- + * TkMacOSXSetUpDrawingContext -- * - * Set up a CGContext for the given graphics port. + * Set up a drawing context for the given drawable and GC. * * Results: - * None. + * Boolean indicating whether to use CG drawing. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ -static void -TkMacOSXSetUpCGContext( - MacDrawable *macWin, - CGrafPtr destPort, - GC gc, - CGContextRef *contextPtr) +int +TkMacOSXSetupDrawingContext(Drawable d, GC gc, int useCG, + TkMacOSXDrawingContext *dc) { - RGBColor macColor; - CGContextRef outContext; - OSStatus err; - Rect boundsRect; - CGAffineTransform coordsTransform; - static RgnHandle clipRgn = NULL; - float w; - - err = QDBeginCGContext(destPort, contextPtr); - outContext = *contextPtr; - - /* - * Now clip the CG Context to the port. Note, we have already - * set up the port with our clip region, so we can just get - * the clip back out of there. If we use the macWin->clipRgn - * directly at this point, we get some odd drawing effects. - * - * We also have to intersect our clip region with the port - * visible region so we don't overwrite the window decoration. - */ - - if (!clipRgn) { - clipRgn = NewRgn(); + MacDrawable *macDraw = ((MacDrawable*)d); + CGContextRef context = macDraw->context; + CGrafPtr port; + Rect portBounds; + + port = TkMacOSXGetDrawablePort(d); + if (port) { + GetPortBounds(port, &portBounds); } - GetPortBounds(destPort, &boundsRect); - - RectRgn(clipRgn, &boundsRect); - SectRegionWithPortClipRegion(destPort, clipRgn); - SectRegionWithPortVisibleRegion(destPort, clipRgn); - ClipCGContextToRegion(outContext, &boundsRect, clipRgn); - SetEmptyRgn(clipRgn); + dc->saveState = NULL; + if (port && !context) { + dc->portChanged = QDSwapPort(port, &(dc->savePort)); + TkMacOSXSetUpClippingRgn(d); + TkMacOSXCheckTmpRgnEmpty(1); + if (useCG) { + if (ChkErr(QDBeginCGContext, port, &context) == noErr) { + /* + * Now clip the CG Context to the port. Note, we have already + * set up the port with our clip region, so we can just get + * the clip back out of there. If we use the macWin->clipRgn + * directly at this point, we get some odd drawing effects. + * + * We also have to intersect our clip region with the port + * visible region so we don't overwrite the window decoration. + */ + + RectRgn(tkMacOSXtmpRgn1, &portBounds); + SectRegionWithPortClipRegion(port, tkMacOSXtmpRgn1); + SectRegionWithPortVisibleRegion(port, tkMacOSXtmpRgn1); + if (gc && gc->clip_mask && ((TkpClipMask*)gc->clip_mask)->type + == TKP_CLIP_REGION) { + RgnHandle clipRgn = (RgnHandle) + ((TkpClipMask*)gc->clip_mask)->value.region; + int xOffset = macDraw->xOff + gc->clip_x_origin; + int yOffset = macDraw->yOff + gc->clip_y_origin; + + OffsetRgn(clipRgn, xOffset, yOffset); + SectRgn(clipRgn, tkMacOSXtmpRgn1, tkMacOSXtmpRgn1); + OffsetRgn(clipRgn, -xOffset, -yOffset); + } + ClipCGContextToRegion(context, &portBounds, tkMacOSXtmpRgn1); + SetEmptyRgn(tkMacOSXtmpRgn1); - /* - * Note: You have to call SyncCGContextOriginWithPort - * AFTER all the clip region manipulations. - */ + /* + * Note: You have to call SyncCGContextOriginWithPort + * AFTER all the clip region manipulations. + */ - SyncCGContextOriginWithPort(outContext, destPort); - - coordsTransform = CGAffineTransformMake(1, 0, 0, -1, 0, - boundsRect.bottom - boundsRect.top); - CGContextConcatCTM(outContext, coordsTransform); - - /* Now offset the CTM to the subwindow offset */ - - if (TkSetMacColor(gc->foreground, &macColor) == true) { - CGContextSetRGBFillColor(outContext, - RGBFLOATRED(macColor), - RGBFLOATGREEN(macColor), - RGBFLOATBLUE(macColor), - 1); - CGContextSetRGBStrokeColor(outContext, - RGBFLOATRED(macColor), - RGBFLOATGREEN(macColor), - RGBFLOATBLUE(macColor), - 1); - } + SyncCGContextOriginWithPort(context, port); + } else { + context = NULL; + useCG = 0; + } + } + } else if (context) { +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 + if (!port +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1030 + && CGContextGetClipBoundingBox != NULL +#endif + ) { + CGRect r = CGContextGetClipBoundingBox(context); - if(gc->function == GXxor) { - } + SetRect(&portBounds, r.origin.x + macDraw->xOff, + r.origin.y + macDraw->yOff, + r.origin.x + r.size.width + macDraw->xOff, + r.origin.y + r.size.height + macDraw->yOff); + } +#endif + CGContextSaveGState(context); + TkMacOSXCheckTmpRgnEmpty(1); + RectRgn(tkMacOSXtmpRgn1, &portBounds); + if (port) { + TkMacOSXSetUpClippingRgn(d); + SectRegionWithPortClipRegion(port, tkMacOSXtmpRgn1); + SectRegionWithPortVisibleRegion(port, tkMacOSXtmpRgn1); + } else if (macDraw->flags & TK_CLIPPED_DRAW) { + OffsetRgn(macDraw->drawRgn, macDraw->xOff, macDraw->yOff); + SectRgn(macDraw->clipRgn, macDraw->drawRgn, tkMacOSXtmpRgn1); + OffsetRgn(macDraw->drawRgn, -macDraw->xOff, -macDraw->yOff); + } + if (gc && gc->clip_mask && ((TkpClipMask*)gc->clip_mask)->type + == TKP_CLIP_REGION) { + RgnHandle clipRgn = (RgnHandle) + ((TkpClipMask*)gc->clip_mask)->value.region; + int xOffset = macDraw->xOff + gc->clip_x_origin; + int yOffset = macDraw->yOff + gc->clip_y_origin; - w = gc->line_width; - /* When should we antialias? */ - if (notAA(gc->line_width)) { - /* Make non-antialiased CG drawing look more like X11 */ - w -= (gc->line_width ? NON_AA_CG_OFFSET : 0); - CGContextSetShouldAntialias(outContext, 0); - } else { - CGContextSetShouldAntialias(outContext, 1); + OffsetRgn(clipRgn, xOffset, yOffset); + SectRgn(clipRgn, tkMacOSXtmpRgn1, tkMacOSXtmpRgn1); + OffsetRgn(clipRgn, -xOffset, -yOffset); + } + ClipCGContextToRegion(context, &portBounds, tkMacOSXtmpRgn1); + SetEmptyRgn(tkMacOSXtmpRgn1); + port = NULL; + dc->portChanged = false; + dc->saveState = (void*)1; + useCG = 1; } - CGContextSetLineWidth(outContext, w); + if (useCG) { + CGContextConcatCTM(context, CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, + 0.0, portBounds.bottom - portBounds.top)); + if (gc) { + double w = gc->line_width; + + TkMacOSXSetColorInContext(gc->foreground, context); + if (port) { + CGContextSetPatternPhase(context, CGSizeMake(portBounds.right - + portBounds.left, portBounds.bottom - portBounds.top)); + } + if(gc->function == GXxor) { + TkMacOSXDbgMsg("GXxor mode not supported for CG drawing!"); + } + /* When should we antialias? */ + if (notAA(gc->line_width)) { + /* Make non-antialiased CG drawing look more like X11 */ + w -= (gc->line_width ? NON_AA_CG_OFFSET : 0); + CGContextSetShouldAntialias(context, 0); + } else { + CGContextSetShouldAntialias(context, 1); + } + CGContextSetLineWidth(context, w); - if (gc->line_style != LineSolid) { - int num = 0; - char *p = &(gc->dashes); - float dashOffset = gc->dash_offset; - float lengths[10]; + if (gc->line_style != LineSolid) { + int num = 0; + char *p = &(gc->dashes); + double dashOffset = gc->dash_offset; + float lengths[10]; - while (p[num] != '\0') { - lengths[num] = p[num]; - num++; - } - CGContextSetLineDash(outContext, dashOffset, lengths, num); - } + while (p[num] != '\0' && num < 10) { + lengths[num] = p[num]; + num++; + } + CGContextSetLineDash(context, dashOffset, lengths, num); + } - if (gc->cap_style == CapButt) { - /* - * What about CapNotLast, CapProjecting? - */ + if (gc->cap_style == CapButt) { + /* + * What about CapNotLast, CapProjecting? + */ - CGContextSetLineCap(outContext, kCGLineCapButt); - } else if (gc->cap_style == CapRound) { - CGContextSetLineCap(outContext, kCGLineCapRound); - } else if (gc->cap_style == CapProjecting) { - CGContextSetLineCap(outContext, kCGLineCapSquare); - } + CGContextSetLineCap(context, kCGLineCapButt); + } else if (gc->cap_style == CapRound) { + CGContextSetLineCap(context, kCGLineCapRound); + } else if (gc->cap_style == CapProjecting) { + CGContextSetLineCap(context, kCGLineCapSquare); + } - if (gc->join_style == JoinMiter) { - CGContextSetLineJoin(outContext, kCGLineJoinMiter); - } else if (gc->join_style == JoinRound) { - CGContextSetLineJoin(outContext, kCGLineJoinRound); - } else if (gc->join_style == JoinBevel) { - CGContextSetLineJoin(outContext, kCGLineJoinBevel); + if (gc->join_style == JoinMiter) { + CGContextSetLineJoin(context, kCGLineJoinMiter); + } else if (gc->join_style == JoinRound) { + CGContextSetLineJoin(context, kCGLineJoinRound); + } else if (gc->join_style == JoinBevel) { + CGContextSetLineJoin(context, kCGLineJoinBevel); + } + } + } else { + ChkErr(GetThemeDrawingState, &(dc->saveState)); + if (gc) { + PixPatHandle savePat = gPenPat; + + gPenPat = NULL; + TkMacOSXSetUpGraphicsPort(gc, port); + dc->penPat = gPenPat; + gPenPat = savePat; + if (gc->clip_mask && ((TkpClipMask*)gc->clip_mask)->type + == TKP_CLIP_REGION) { + RgnHandle clipRgn = (RgnHandle) + ((TkpClipMask*)gc->clip_mask)->value.region; + int xOffset = macDraw->xOff + gc->clip_x_origin; + int yOffset = macDraw->yOff + gc->clip_y_origin; + + OffsetRgn(clipRgn, xOffset, yOffset); + GetClip(tkMacOSXtmpRgn1); + SectRgn(clipRgn, tkMacOSXtmpRgn1, tkMacOSXtmpRgn1); + SetClip(tkMacOSXtmpRgn1); + SetEmptyRgn(tkMacOSXtmpRgn1); + OffsetRgn(clipRgn, -xOffset, -yOffset); + } + } else { + TkMacOSXSetUpGraphicsPort(NULL, port); + dc->penPat = NULL; + } + ShowPen(); } + dc->port = port; + dc->portBounds = portBounds; + dc->context = context; + return useCG; } /* *---------------------------------------------------------------------- * - * TkMacOSXReleaseCGContext -- + * TkMacOSXRestoreDrawingContext -- * - * Release the CGContext for the given graphics port. + * Restore drawing context. * * Results: - * None. + * None. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ -static void -TkMacOSXReleaseCGContext( - MacDrawable *macWin, - CGrafPtr destPort, - CGContextRef *outContext) +void +TkMacOSXRestoreDrawingContext(TkMacOSXDrawingContext *dc) { - CGContextSynchronize(*outContext); - QDEndCGContext(destPort, outContext); + if (dc->context) { + CGContextSynchronize(dc->context); + if (dc->saveState) { + CGContextRestoreGState(dc->context); + } + if (dc->port) { + ChkErr(QDEndCGContext, dc->port, &(dc->context)); + } + } else { + HidePen(); + PenNormal(); + if (dc->penPat) { + DisposePixPat(dc->penPat); + } + if (dc->saveState) { + ChkErr(SetThemeDrawingState, dc->saveState, true); + } + } + if (dc->portChanged) { + QDSwapPort(dc->savePort, NULL); + } +#ifdef TK_MAC_DEBUG + bzero(dc, sizeof(dc)); +#endif /* TK_MAC_DEBUG */ } /* @@ -1917,21 +1841,21 @@ TkMacOSXReleaseCGContext( * * TkMacOSXSetUpClippingRgn -- * - * Set up the clipping region so that drawing only occurs on the - * specified X subwindow. + * Set up the clipping region so that drawing only occurs on the + * specified X subwindow. * * Results: - * None. + * None. * * Side effects: - * The clipping region in the current port is changed. + * The clipping region in the current port is changed. * *---------------------------------------------------------------------- */ void TkMacOSXSetUpClippingRgn( - Drawable drawable) /* Drawable to update. */ + Drawable drawable) /* Drawable to update. */ { MacDrawable *macDraw = (MacDrawable *) drawable; @@ -1940,43 +1864,72 @@ TkMacOSXSetUpClippingRgn( TkMacOSXUpdateClipRgn(macDraw->winPtr); } -#if defined(TK_MAC_DEBUG) && defined(TK_MAC_DEBUG_DRAWING) +#ifdef TK_MAC_DEBUG_DRAWING TkMacOSXInitNamedDebugSymbol(HIToolbox, int, QDDebugFlashRegion, - CGrafPtr port, RgnHandle region); + CGrafPtr port, RgnHandle region); if (QDDebugFlashRegion) { CGrafPtr grafPtr = TkMacOSXGetDrawablePort(drawable); - /* Carbon-internal region flashing SPI (c.f. Technote 2124) */ + + /* + * Carbon-internal region flashing SPI (c.f. Technote 2124) + */ + QDDebugFlashRegion(grafPtr, macDraw->clipRgn); } #endif /* TK_MAC_DEBUG_DRAWING */ + } - /* - * When a menu is up, the Mac does not expect drawing to occur and - * does not clip out the menu. We have to do it ourselves. This - * is pretty gross. - */ + if (macDraw->clipRgn != NULL) { + if (macDraw->flags & TK_CLIPPED_DRAW) { + TkMacOSXCheckTmpRgnEmpty(1); + OffsetRgn(macDraw->drawRgn, macDraw->xOff, macDraw->yOff); + SectRgn(macDraw->clipRgn, macDraw->drawRgn, tkMacOSXtmpRgn1); + OffsetRgn(macDraw->drawRgn, -macDraw->xOff, -macDraw->yOff); + SetClip(tkMacOSXtmpRgn1); + SetEmptyRgn(tkMacOSXtmpRgn1); + } else { + SetClip(macDraw->clipRgn); + } + } else if (macDraw->flags & TK_CLIPPED_DRAW) { + OffsetRgn(macDraw->drawRgn, macDraw->xOff, macDraw->yOff); + SetClip(macDraw->drawRgn); + OffsetRgn(macDraw->drawRgn, -macDraw->xOff, -macDraw->yOff); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpClipDrawableToRect -- + * + * Clip all drawing into the drawable d to the given rectangle. + * If width and height are negative, reset to no clipping. + * + * Results: + * None. + * + * Side effects: + * Subsequent drawing into d is offset and clipped as specified. + * + *---------------------------------------------------------------------- + */ - if (macDraw->clipRgn != NULL) { - if (tkUseMenuCascadeRgn == 1) { - Point scratch = {0, 0}; - GDHandle saveDevice; - GWorldPtr saveWorld; - - GetGWorld(&saveWorld, &saveDevice); - SetGWorld(TkMacOSXGetDrawablePort(drawable), NULL); - LocalToGlobal(&scratch); - SetGWorld(saveWorld, saveDevice); - if (tmpRgn == NULL) { - tmpRgn = NewRgn(); - } - CopyRgn(tkMenuCascadeRgn, tmpRgn); - OffsetRgn(tmpRgn, -scratch.h, -scratch.v); - DiffRgn(macDraw->clipRgn, tmpRgn, tmpRgn); - SetClip(tmpRgn); - macDraw->toplevel->flags |= TK_DRAWN_UNDER_MENU; - } else { - SetClip(macDraw->clipRgn); - } +void +TkpClipDrawableToRect( + Display *display, + Drawable d, + int x, int y, + int width, int height) +{ + MacDrawable *macDraw = (MacDrawable *) d; + + if (macDraw->drawRgn) { + if (width < 0 && height < 0) { + SetEmptyRgn(macDraw->drawRgn); + macDraw->flags &= ~TK_CLIPPED_DRAW; + } else { + SetRectRgn(macDraw->drawRgn, x, y, x + width, y + height); + macDraw->flags |= TK_CLIPPED_DRAW; } } } @@ -1986,48 +1939,45 @@ TkMacOSXSetUpClippingRgn( * * TkMacOSXMakeStippleMap -- * - * Given a drawable and a stipple pattern this function draws the - * pattern repeatedly over the drawable. The drawable can then - * be used as a mask for bit-bliting a stipple pattern over an - * object. + * Given a drawable and a stipple pattern this function draws the + * pattern repeatedly over the drawable. The drawable can then + * be used as a mask for bit-bliting a stipple pattern over an + * object. * * Results: - * A BitMap data structure. + * A BitMap data structure. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ BitMapPtr TkMacOSXMakeStippleMap( - Drawable drawable, /* Window to apply stipple. */ - Drawable stipple) /* The stipple pattern. */ + Drawable drawable, /* Window to apply stipple. */ + Drawable stipple) /* The stipple pattern. */ { - GWorldPtr destPort; + CGrafPtr stipplePort; BitMapPtr bitmapPtr; - Rect portRect; - int width, height, stippleHeight, stippleWidth; - int i, j; - char * data; + const BitMap *stippleBitmap; + Rect portRect; + int width, height, stippleHeight, stippleWidth, i, j; Rect bounds; - destPort = TkMacOSXGetDrawablePort(drawable); - - GetPortBounds (destPort, &portRect); + GetPortBounds(TkMacOSXGetDrawablePort(drawable), &portRect); width = portRect.right - portRect.left; height = portRect.bottom - portRect.top; - bitmapPtr = (BitMap *) ckalloc(sizeof(BitMap)); - data = (char *) ckalloc(height * ((width / 8) + 1)); bitmapPtr->bounds.top = bitmapPtr->bounds.left = 0; bitmapPtr->bounds.right = (short) width; bitmapPtr->bounds.bottom = (short) height; - bitmapPtr->baseAddr = data; bitmapPtr->rowBytes = (width / 8) + 1; + bitmapPtr->baseAddr = ckalloc(height * bitmapPtr->rowBytes); - destPort = TkMacOSXGetDrawablePort(stipple); + stipplePort = TkMacOSXGetDrawablePort(stipple); + stippleBitmap = GetPortBitMapForCopyBits(stipplePort); + GetPortBounds(stipplePort, &portRect); stippleWidth = portRect.right - portRect.left; stippleHeight = portRect.bottom - portRect.top; @@ -2037,9 +1987,8 @@ TkMacOSXMakeStippleMap( bounds.top = i; bounds.right = j + stippleWidth; bounds.bottom = i + stippleHeight; - - CopyBits(GetPortBitMapForCopyBits(destPort), bitmapPtr, - &portRect, &bounds, srcCopy, NULL); + CopyBits(stippleBitmap, bitmapPtr, &portRect, &bounds, srcCopy, + NULL); } } return bitmapPtr; @@ -2050,20 +1999,20 @@ TkMacOSXMakeStippleMap( * * InvertByte -- * - * This function reverses the bits in the passed in Byte of data. + * This function reverses the bits in the passed in Byte of data. * * Results: - * The incoming byte in reverse bit order. + * The incoming byte in reverse bit order. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ static unsigned char InvertByte( - unsigned char data) /* Byte of data. */ + unsigned char data) /* Byte of data. */ { unsigned char i; unsigned char mask = 1, result = 0; @@ -2082,32 +2031,32 @@ InvertByte( * * TkpDrawHighlightBorder -- * - * This procedure draws a rectangular ring around the outside of - * a widget to indicate that it has received the input focus. + * This procedure draws a rectangular ring around the outside of + * a widget to indicate that it has received the input focus. * - * On the Macintosh, this puts a 1 pixel border in the bgGC color - * between the widget and the focus ring, except in the case where - * highlightWidth is 1, in which case the border is left out. + * On the Macintosh, this puts a 1 pixel border in the bgGC color + * between the widget and the focus ring, except in the case where + * highlightWidth is 1, in which case the border is left out. * - * For proper Mac L&F, use highlightWidth of 3. + * For proper Mac L&F, use highlightWidth of 3. * * Results: - * None. + * None. * * Side effects: - * A rectangle "width" pixels wide is drawn in "drawable", - * corresponding to the outer area of "tkwin". + * A rectangle "width" pixels wide is drawn in "drawable", + * corresponding to the outer area of "tkwin". * *---------------------------------------------------------------------- */ void TkpDrawHighlightBorder ( - Tk_Window tkwin, - GC fgGC, - GC bgGC, - int highlightWidth, - Drawable drawable) + Tk_Window tkwin, + GC fgGC, + GC bgGC, + int highlightWidth, + Drawable drawable) { if (highlightWidth == 1) { TkDrawInsetFocusHighlight (tkwin, fgGC, highlightWidth, drawable, 0); @@ -2125,7 +2074,7 @@ TkpDrawHighlightBorder ( * * TkpDrawFrame -- * - * This procedure draws the rectangular frame area. If the user + * This procedure draws the rectangular frame area. If the user * has request themeing, it draws with a the background theme. * * Results: @@ -2138,52 +2087,27 @@ TkpDrawHighlightBorder ( */ void -TkpDrawFrame (Tk_Window tkwin, Tk_3DBorder border, - int highlightWidth, int borderWidth, int relief) +TkpDrawFrame( + Tk_Window tkwin, + Tk_3DBorder border, + int highlightWidth, + int borderWidth, + int relief) { if (useThemedToplevel && Tk_IsTopLevel(tkwin)) { - /* - * Currently only support themed toplevels, until we can better - * factor this to handle individual windows (blanket theming of - * frames will work for very few UIs). - */ - Rect bounds; - Point origin; - CGrafPtr saveWorld; - GDHandle saveDevice; - XGCValues gcValues; - GC gc; - Pixmap pixmap; - Display *display = Tk_Display(tkwin); - - pixmap = Tk_GetPixmap(display, Tk_WindowId(tkwin), - Tk_Width(tkwin), Tk_Height(tkwin), Tk_Depth(tkwin)); - - gc = Tk_GetGC(tkwin, 0, &gcValues); - TkMacOSXWinBounds((TkWindow *) tkwin, &bounds); - origin.v = -bounds.top; - origin.h = -bounds.left; - bounds.top = bounds.left = 0; - bounds.right = Tk_Width(tkwin); - bounds.bottom = Tk_Height(tkwin); - - GetGWorld(&saveWorld, &saveDevice); - SetGWorld(TkMacOSXGetDrawablePort(pixmap), 0); - ApplyThemeBackground(kThemeBackgroundWindowHeader, &bounds, - kThemeStateActive, 32 /* depth */, true /* inColor */); - QDSetPatternOrigin(origin); - EraseRect(&bounds); - SetGWorld(saveWorld, saveDevice); - - XCopyArea(display, pixmap, Tk_WindowId(tkwin), - gc, 0, 0, bounds.right, bounds.bottom, 0, 0); - Tk_FreePixmap(display, pixmap); - Tk_FreeGC(display, gc); - } else { - Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), - border, highlightWidth, highlightWidth, - Tk_Width(tkwin) - 2 * highlightWidth, - Tk_Height(tkwin) - 2 * highlightWidth, - borderWidth, relief); + static Tk_3DBorder themedBorder = NULL; + + if (!themedBorder) { + themedBorder = Tk_Get3DBorder(NULL, tkwin, + "systemWindowHeaderBackground"); + } + if (themedBorder) { + border = themedBorder; + } } + Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), + border, highlightWidth, highlightWidth, + Tk_Width(tkwin) - 2 * highlightWidth, + Tk_Height(tkwin) - 2 * highlightWidth, + borderWidth, relief); } diff --git a/macosx/tkMacOSXEmbed.c b/macosx/tkMacOSXEmbed.c index c82a649..bfd500c 100644 --- a/macosx/tkMacOSXEmbed.c +++ b/macosx/tkMacOSXEmbed.c @@ -1,51 +1,52 @@ -/* +/* * tkMacOSXEmbed.c -- * - * This file contains platform-specific procedures for theMac to provide - * basic operations needed for application embedding (where one - * application can use as its main window an internal window from - * some other application). - * Currently only Toplevel embedding within the same Tk application is - * allowed on the Macintosh. + * This file contains platform-specific procedures for theMac to provide + * basic operations needed for application embedding (where one + * application can use as its main window an internal window from + * some other application). + * Currently only Toplevel embedding within the same Tk application is + * allowed on the Macintosh. * * Copyright (c) 1996-1997 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2006-2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXEmbed.c,v 1.8 2006/10/31 22:33:34 das Exp $ + * RCS: @(#) $Id: tkMacOSXEmbed.c,v 1.9 2007/04/23 21:24:33 das Exp $ */ #include "tkMacOSXInt.h" /* * One of the following structures exists for each container in this - * application. It keeps track of the container window and its + * application. It keeps track of the container window and its * associated embedded window. */ typedef struct Container { - Window parent; /* The Mac Drawable for the parent of - * the pair (the container). */ - TkWindow *parentPtr; /* Tk's information about the container, - * or NULL if the container isn't - * in this process. */ - Window embedded; /* The MacDrawable for the embedded - * window. Starts off as None, but - * gets filled in when the window is - * eventually created. */ - TkWindow *embeddedPtr; /* Tk's information about the embedded - * window, or NULL if the - * embedded application isn't in - * this process. */ - struct Container *nextPtr; /* Next in list of all containers in - * this process. */ + Window parent; /* The Mac Drawable for the parent of + * the pair (the container). */ + TkWindow *parentPtr; /* Tk's information about the container, + * or NULL if the container isn't + * in this process. */ + Window embedded; /* The MacDrawable for the embedded + * window. Starts off as None, but + * gets filled in when the window is + * eventually created. */ + TkWindow *embeddedPtr; /* Tk's information about the embedded + * window, or NULL if the + * embedded application isn't in + * this process. */ + struct Container *nextPtr; /* Next in list of all containers in + * this process. */ } Container; static Container *firstContainerPtr = NULL; - /* First in list of all containers - * managed by this process. */ + /* First in list of all containers + * managed by this process. */ /* * Globals defined in this file */ @@ -56,21 +57,15 @@ TkMacOSXEmbedHandler *tkMacOSXEmbedHandler = NULL; * Prototypes for static procedures defined in this file: */ -static void ContainerEventProc _ANSI_ARGS_(( - ClientData clientData, XEvent *eventPtr)); -static void EmbeddedEventProc _ANSI_ARGS_(( - ClientData clientData, XEvent *eventPtr)); -static void EmbedActivateProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static void EmbedFocusProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static void EmbedGeometryRequest _ANSI_ARGS_(( - Container * containerPtr, int width, int height)); -static void EmbedSendConfigure _ANSI_ARGS_(( - Container *containerPtr)); -static void EmbedStructureProc _ANSI_ARGS_((ClientData clientData, - XEvent *eventPtr)); -static void EmbedWindowDeleted _ANSI_ARGS_((TkWindow *winPtr)); +static void ContainerEventProc(ClientData clientData, XEvent *eventPtr); +static void EmbeddedEventProc(ClientData clientData, XEvent *eventPtr); +static void EmbedActivateProc(ClientData clientData, XEvent *eventPtr); +static void EmbedFocusProc(ClientData clientData, XEvent *eventPtr); +static void EmbedGeometryRequest(Container * containerPtr, int width, + int height); +static void EmbedSendConfigure(Container *containerPtr); +static void EmbedStructureProc(ClientData clientData, XEvent *eventPtr); +static void EmbedWindowDeleted(TkWindow *winPtr); /* @@ -78,15 +73,15 @@ static void EmbedWindowDeleted _ANSI_ARGS_((TkWindow *winPtr)); * * Tk_MacOSXSetEmbedHandler -- * - * Registers a handler for an in process form of embedding, like - * Netscape plugins, where Tk is loaded into the process, but does - * not control the main window + * Registers a handler for an in process form of embedding, like + * Netscape plugins, where Tk is loaded into the process, but does + * not control the main window * * Results: - * None + * None * * Side effects: - * The embed handler is set. + * The embed handler is set. * *---------------------------------------------------------------------- */ @@ -99,28 +94,27 @@ Tk_MacOSXSetEmbedHandler( Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc) { if (tkMacOSXEmbedHandler == NULL) { - tkMacOSXEmbedHandler = (TkMacOSXEmbedHandler *) ckalloc(sizeof(TkMacOSXEmbedHandler)); + tkMacOSXEmbedHandler = (TkMacOSXEmbedHandler *) ckalloc(sizeof(TkMacOSXEmbedHandler)); } tkMacOSXEmbedHandler->registerWinProc = registerWinProc; tkMacOSXEmbedHandler->getPortProc = getPortProc; tkMacOSXEmbedHandler->containerExistProc = containerExistProc; tkMacOSXEmbedHandler->getClipProc = getClipProc; - tkMacOSXEmbedHandler->getOffsetProc = getOffsetProc; + tkMacOSXEmbedHandler->getOffsetProc = getOffsetProc; } - /* *---------------------------------------------------------------------- * * TkpMakeWindow -- * - * Creates an X Window (Mac subwindow). + * Creates an X Window (Mac subwindow). * * Results: - * The window id is returned. + * The window id is returned. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ @@ -138,57 +132,55 @@ TkpMakeWindow( * the window structure should have already been * created in the TkpUseWindow function. */ - + if (Tk_IsEmbedded(winPtr)) { - return (Window) winPtr->privatePtr; + return (Window) winPtr->privatePtr; } - + /* * Allocate sub window */ - + macWin = (MacDrawable *) ckalloc(sizeof(MacDrawable)); if (macWin == NULL) { - winPtr->privatePtr = NULL; - return None; + winPtr->privatePtr = NULL; + return None; } macWin->winPtr = winPtr; winPtr->privatePtr = macWin; macWin->clipRgn = NewRgn(); macWin->aboveClipRgn = NewRgn(); + macWin->drawRgn = NewRgn(); macWin->referenceCount = 0; macWin->flags = TK_CLIP_INVALID; + macWin->grafPtr = NULL; + macWin->context = NULL; if (Tk_IsTopLevel(macWin->winPtr)) { - - /* - *This will be set when we are mapped. - */ - - macWin->grafPtr = NULL; - macWin->toplevel = macWin; - macWin->xOff = 0; - macWin->yOff = 0; + /* + *This will be set when we are mapped. + */ + macWin->xOff = 0; + macWin->yOff = 0; + macWin->toplevel = macWin; } else { - macWin->grafPtr = NULL; - macWin->xOff = winPtr->parentPtr->privatePtr->xOff + - winPtr->parentPtr->changes.border_width + - winPtr->changes.x; - macWin->yOff = winPtr->parentPtr->privatePtr->yOff + - winPtr->parentPtr->changes.border_width + - winPtr->changes.y; - macWin->toplevel = winPtr->parentPtr->privatePtr->toplevel; + macWin->xOff = winPtr->parentPtr->privatePtr->xOff + + winPtr->parentPtr->changes.border_width + + winPtr->changes.x; + macWin->yOff = winPtr->parentPtr->privatePtr->yOff + + winPtr->parentPtr->changes.border_width + + winPtr->changes.y; + macWin->toplevel = winPtr->parentPtr->privatePtr->toplevel; } - macWin->toplevel->referenceCount++; - - /* + + /* * TODO: need general solution for visibility events. */ event.xany.serial = Tk_Display(winPtr)->request; event.xany.send_event = False; event.xany.display = Tk_Display(winPtr); - + event.xvisibility.type = VisibilityNotify; event.xvisibility.window = (Window) macWin; event.xvisibility.state = VisibilityUnobscured; @@ -202,31 +194,31 @@ TkpMakeWindow( * * TkpUseWindow -- * - * This procedure causes a Tk window to use a given X window as - * its parent window, rather than the root window for the screen. - * It is invoked by an embedded application to specify the window - * in which it is embedded. + * This procedure causes a Tk window to use a given X window as + * its parent window, rather than the root window for the screen. + * It is invoked by an embedded application to specify the window + * in which it is embedded. * * Results: - * The return value is normally TCL_OK. If an error occurs (such - * as string not being a valid window spec), then the return value - * is TCL_ERROR and an error message is left in the interp's result if - * interp is non-NULL. + * The return value is normally TCL_OK. If an error occurs (such + * as string not being a valid window spec), then the return value + * is TCL_ERROR and an error message is left in the interp's result if + * interp is non-NULL. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ int TkpUseWindow( - Tcl_Interp *interp, /* If not NULL, used for error reporting - * if string is bogus. */ - Tk_Window tkwin, /* Tk window that does not yet have an - * associated X window. */ - CONST char *string) /* String identifying an X window to use - * for tkwin; must be an integer value. */ + Tcl_Interp *interp, /* If not NULL, used for error reporting + * if string is bogus. */ + Tk_Window tkwin, /* Tk window that does not yet have an + * associated X window. */ + CONST char *string) /* String identifying an X window to use + * for tkwin; must be an integer value. */ { TkWindow *winPtr = (TkWindow *) tkwin; TkWindow *usePtr; @@ -235,12 +227,13 @@ TkpUseWindow( XEvent event; if (winPtr->window != None) { - Tcl_AppendResult(interp, "can't modify container after widget is created", (char *) NULL); + Tcl_AppendResult(interp, "can't modify container after widget is " + "created", NULL); return TCL_ERROR; } - + /* - * Decode the container pointer, and look for it among the + * Decode the container pointer, and look for it among the *list of available containers. * * N.B. For now, we are limiting the containers to be in the same Tk @@ -248,9 +241,9 @@ TkpUseWindow( * of containers. * */ - + if (Tcl_GetInt(interp, string, (int*) &parent) != TCL_OK) { - return TCL_ERROR; + return TCL_ERROR; } usePtr = (TkWindow *) Tk_IdToWindow(winPtr->display, (Window) parent); @@ -261,158 +254,159 @@ TkpUseWindow( return TCL_ERROR; } } - - /* + + /* * The code below can probably be simplified given we have already * discovered 'usePtr' above. */ /* * Save information about the container and the embedded window - * in a Container structure. Currently, there must already be an existing - * Container structure, since we only allow the case where both container + * in a Container structure. Currently, there must already be an existing + * Container structure, since we only allow the case where both container * and embedded app. are in the same process. */ for (containerPtr = firstContainerPtr; containerPtr != NULL; - containerPtr = containerPtr->nextPtr) { - if (containerPtr->parent == (Window) parent) { - winPtr->flags |= TK_BOTH_HALVES; - containerPtr->parentPtr->flags |= TK_BOTH_HALVES; - break; - } + containerPtr = containerPtr->nextPtr) { + if (containerPtr->parent == (Window) parent) { + winPtr->flags |= TK_BOTH_HALVES; + containerPtr->parentPtr->flags |= TK_BOTH_HALVES; + break; + } } - + /* - * Make the embedded window. + * Make the embedded window. */ macWin = (MacDrawable *) ckalloc(sizeof(MacDrawable)); if (macWin == NULL) { - winPtr->privatePtr = NULL; - return TCL_ERROR; + winPtr->privatePtr = NULL; + return TCL_ERROR; } - + macWin->winPtr = winPtr; winPtr->privatePtr = macWin; /* * The grafPtr will be NULL for a Tk in Tk embedded window. * It is none of our business what it is for a Tk not in Tk embedded window, - * but we will initialize it to NULL, and let the registerWinProc - * set it. In any case, you must always use TkMacOSXGetDrawablePort - * to get the portPtr. It will correctly find the container's port. + * but we will initialize it to NULL, and let the registerWinProc + * set it. In any case, you must always use TkMacOSXGetDrawablePort + * to get the portPtr. It will correctly find the container's port. */ macWin->grafPtr = NULL; + macWin->context = NULL; macWin->clipRgn = NewRgn(); macWin->aboveClipRgn = NewRgn(); + macWin->drawRgn = NewRgn(); macWin->referenceCount = 0; macWin->flags = TK_CLIP_INVALID; macWin->toplevel = macWin; macWin->toplevel->referenceCount++; - + winPtr->flags |= TK_EMBEDDED; - - + + /* * Make a copy of the TK_EMBEDDED flag, since sometimes * we need this to get the port after the TkWindow structure * has been freed. */ - + macWin->flags |= TK_EMBEDDED; - + /* - * Now check whether it is embedded in another Tk widget. If not (the first + * Now check whether it is embedded in another Tk widget. If not (the first * case below) we see if there is an in-process embedding handler registered, * and if so, let that fill in the rest of the macWin. */ - + if (containerPtr == NULL) { - /* - * If someone has registered an in process embedding handler, then - * see if it can handle this window... - */ - - if (tkMacOSXEmbedHandler == NULL || - tkMacOSXEmbedHandler->registerWinProc((int) parent, - (Tk_Window) winPtr) != TCL_OK) { - Tcl_AppendResult(interp, "The window ID ", string, - " does not correspond to a valid Tk Window.", - (char *) NULL); - return TCL_ERROR; - } else { - containerPtr = (Container *) ckalloc(sizeof(Container)); - - containerPtr->parentPtr = NULL; - containerPtr->embedded = (Window) macWin; - containerPtr->embeddedPtr = macWin->winPtr; - containerPtr->nextPtr = firstContainerPtr; - firstContainerPtr = containerPtr; - - } + /* + * If someone has registered an in process embedding handler, then + * see if it can handle this window... + */ + + if (tkMacOSXEmbedHandler == NULL || + tkMacOSXEmbedHandler->registerWinProc((int) parent, + (Tk_Window) winPtr) != TCL_OK) { + Tcl_AppendResult(interp, "The window ID ", string, + " does not correspond to a valid Tk Window.", NULL); + return TCL_ERROR; + } else { + containerPtr = (Container *) ckalloc(sizeof(Container)); + + containerPtr->parentPtr = NULL; + containerPtr->embedded = (Window) macWin; + containerPtr->embeddedPtr = macWin->winPtr; + containerPtr->nextPtr = firstContainerPtr; + firstContainerPtr = containerPtr; + + } } else { - - /* - * The window is embedded in another Tk window. - */ - - macWin->xOff = parent->winPtr->privatePtr->xOff + - parent->winPtr->changes.border_width + - winPtr->changes.x; - macWin->yOff = parent->winPtr->privatePtr->yOff + - parent->winPtr->changes.border_width + - winPtr->changes.y; - - - /* - * Finish filling up the container structure with the embedded window's - * information. - */ - - containerPtr->embedded = (Window) macWin; - containerPtr->embeddedPtr = macWin->winPtr; - - /* - * Create an event handler to clean up the Container structure when - * tkwin is eventually deleted. - */ - - Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbeddedEventProc, - (ClientData) winPtr); + + /* + * The window is embedded in another Tk window. + */ + + macWin->xOff = parent->winPtr->privatePtr->xOff + + parent->winPtr->changes.border_width + + winPtr->changes.x; + macWin->yOff = parent->winPtr->privatePtr->yOff + + parent->winPtr->changes.border_width + + winPtr->changes.y; + + + /* + * Finish filling up the container structure with the embedded window's + * information. + */ + + containerPtr->embedded = (Window) macWin; + containerPtr->embeddedPtr = macWin->winPtr; + + /* + * Create an event handler to clean up the Container structure when + * tkwin is eventually deleted. + */ + + Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbeddedEventProc, + (ClientData) winPtr); } - /* + /* * TODO: need general solution for visibility events. */ - + event.xany.serial = Tk_Display(winPtr)->request; event.xany.send_event = False; event.xany.display = Tk_Display(winPtr); - + event.xvisibility.type = VisibilityNotify; event.xvisibility.window = (Window) macWin;; event.xvisibility.state = VisibilityUnobscured; Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); - - /* + + /* * TODO: need general solution for visibility events. */ - + event.xany.serial = Tk_Display(winPtr)->request; event.xany.send_event = False; event.xany.display = Tk_Display(winPtr); - + event.xvisibility.type = VisibilityNotify; event.xvisibility.window = (Window) macWin;; event.xvisibility.state = VisibilityUnobscured; Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); - + return TCL_OK; } @@ -421,24 +415,24 @@ TkpUseWindow( * * TkpMakeContainer -- * - * This procedure is called to indicate that a particular window - * will be a container for an embedded application. This changes - * certain aspects of the window's behavior, such as whether it - * will receive events anymore. + * This procedure is called to indicate that a particular window + * will be a container for an embedded application. This changes + * certain aspects of the window's behavior, such as whether it + * will receive events anymore. * * Results: - * None. + * None. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ void TkpMakeContainer( - Tk_Window tkwin) /* Token for a window that is about to - * become a container. */ + Tk_Window tkwin) /* Token for a window that is about to + * become a container. */ { TkWindow *winPtr = (TkWindow *) tkwin; Container *containerPtr; @@ -458,25 +452,25 @@ TkpMakeContainer( containerPtr->nextPtr = firstContainerPtr; firstContainerPtr = containerPtr; winPtr->flags |= TK_CONTAINER; - + /* * Request SubstructureNotify events so that we can find out when * the embedded application creates its window or attempts to - * resize it. Also watch Configure events on the container so that - * we can resize the child to match. Also, pass activate events from + * resize it. Also watch Configure events on the container so that + * we can resize the child to match. Also, pass activate events from * the container down to the embedded toplevel. */ Tk_CreateEventHandler(tkwin, - SubstructureNotifyMask|SubstructureRedirectMask, - ContainerEventProc, (ClientData) winPtr); + SubstructureNotifyMask|SubstructureRedirectMask, + ContainerEventProc, (ClientData) winPtr); Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbedStructureProc, - (ClientData) containerPtr); + (ClientData) containerPtr); Tk_CreateEventHandler(tkwin, ActivateMask, EmbedActivateProc, - (ClientData) containerPtr); + (ClientData) containerPtr); Tk_CreateEventHandler(tkwin, FocusChangeMask, EmbedFocusProc, - (ClientData) containerPtr); - + (ClientData) containerPtr); + } /* @@ -484,30 +478,30 @@ TkpMakeContainer( * * TkMacOSXContainerId -- * - * Given an embedded window, this procedure returns the MacDrawable - * identifier for the associated container window. + * Given an embedded window, this procedure returns the MacDrawable + * identifier for the associated container window. * * Results: - * The return value is the MacDrawable for winPtr's - * container window. + * The return value is the MacDrawable for winPtr's + * container window. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ MacDrawable * TkMacOSXContainerId(winPtr) - TkWindow *winPtr; /* Tk's structure for an embedded window. */ + TkWindow *winPtr; /* Tk's structure for an embedded window. */ { Container *containerPtr; for (containerPtr = firstContainerPtr; containerPtr != NULL; - containerPtr = containerPtr->nextPtr) { - if (containerPtr->embeddedPtr == winPtr) { - return (MacDrawable *) containerPtr->parent; - } + containerPtr = containerPtr->nextPtr) { + if (containerPtr->embeddedPtr == winPtr) { + return (MacDrawable *) containerPtr->parent; + } } Tcl_Panic("TkMacOSXContainerId couldn't find window"); return None; @@ -518,39 +512,39 @@ TkMacOSXContainerId(winPtr) * * TkMacOSXGetHostToplevel -- * - * Given the TkWindow, return the MacDrawable for the outermost - * toplevel containing it. This will be a real Macintosh window. + * Given the TkWindow, return the MacDrawable for the outermost + * toplevel containing it. This will be a real Macintosh window. * * Results: - * Returns a MacDrawable corresponding to a Macintosh Toplevel + * Returns a MacDrawable corresponding to a Macintosh Toplevel * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ MacDrawable * TkMacOSXGetHostToplevel( - TkWindow *winPtr) /* Tk's structure for a window. */ + TkWindow *winPtr) /* Tk's structure for a window. */ { TkWindow *contWinPtr, *topWinPtr; topWinPtr = winPtr->privatePtr->toplevel->winPtr; if (!Tk_IsEmbedded(topWinPtr)) { - return winPtr->privatePtr->toplevel; + return winPtr->privatePtr->toplevel; } else { - contWinPtr = TkpGetOtherWindow(topWinPtr); - - /* - * NOTE: Here we should handle out of process embedding. - */ - - if (contWinPtr != NULL) { - return TkMacOSXGetHostToplevel(contWinPtr); - } else { - return None; - } + contWinPtr = TkpGetOtherWindow(topWinPtr); + + /* + * NOTE: Here we should handle out of process embedding. + */ + + if (contWinPtr != NULL) { + return TkMacOSXGetHostToplevel(contWinPtr); + } else { + return None; + } } } @@ -559,41 +553,41 @@ TkMacOSXGetHostToplevel( * * TkpClaimFocus -- * - * This procedure is invoked when someone asks for the input focus - * to be put on a window in an embedded application, but the - * application doesn't currently have the focus. It requests the - * input focus from the container application. + * This procedure is invoked when someone asks for the input focus + * to be put on a window in an embedded application, but the + * application doesn't currently have the focus. It requests the + * input focus from the container application. * * Results: - * None. + * None. * * Side effects: - * The input focus may change. + * The input focus may change. * *---------------------------------------------------------------------- */ void TkpClaimFocus( - TkWindow *topLevelPtr, /* Top-level window containing desired - * focus window; should be embedded. */ - int force) /* One means that the container should - * claim the focus if it doesn't - * currently have it. */ + TkWindow *topLevelPtr, /* Top-level window containing desired + * focus window; should be embedded. */ + int force) /* One means that the container should + * claim the focus if it doesn't + * currently have it. */ { XEvent event; Container *containerPtr; if (!(topLevelPtr->flags & TK_EMBEDDED)) { - return; + return; } for (containerPtr = firstContainerPtr; - containerPtr->embeddedPtr != topLevelPtr; - containerPtr = containerPtr->nextPtr) { - /* Empty loop body. */ + containerPtr->embeddedPtr != topLevelPtr; + containerPtr = containerPtr->nextPtr) { + /* Empty loop body. */ } - + event.xfocus.type = FocusIn; event.xfocus.serial = LastKnownRequestProcessed(topLevelPtr->display); @@ -610,25 +604,25 @@ TkpClaimFocus( * * TkpTestembedCmd -- * - * This procedure implements the "testembed" command. It returns - * some or all of the information in the list pointed to by - * firstContainerPtr. + * This procedure implements the "testembed" command. It returns + * some or all of the information in the list pointed to by + * firstContainerPtr. * * Results: - * A standard Tcl result. + * A standard Tcl result. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ int TkpTestembedCmd( - ClientData clientData, /* Main window for application. */ - Tcl_Interp *interp, /* Current interpreter. */ - int argc, /* Number of arguments. */ - CONST char **argv) /* Argument strings. */ + ClientData clientData, /* Main window for application. */ + Tcl_Interp *interp, /* Current interpreter. */ + int argc, /* Number of arguments. */ + CONST char **argv) /* Argument strings. */ { int all; Container *containerPtr; @@ -636,47 +630,47 @@ TkpTestembedCmd( char buffer[50]; if ((argc > 1) && (strcmp(argv[1], "all") == 0)) { - all = 1; + all = 1; } else { - all = 0; + all = 0; } Tcl_DStringInit(&dString); for (containerPtr = firstContainerPtr; containerPtr != NULL; - containerPtr = containerPtr->nextPtr) { - Tcl_DStringStartSublist(&dString); - if (containerPtr->parent == None) { - Tcl_DStringAppendElement(&dString, ""); - } else { - if (all) { - sprintf(buffer, "0x%x", (int) containerPtr->parent); - Tcl_DStringAppendElement(&dString, buffer); - } else { - Tcl_DStringAppendElement(&dString, "XXX"); - } - } - if (containerPtr->parentPtr == NULL) { - Tcl_DStringAppendElement(&dString, ""); - } else { - Tcl_DStringAppendElement(&dString, - containerPtr->parentPtr->pathName); - } - if (containerPtr->embedded == None) { - Tcl_DStringAppendElement(&dString, ""); - } else { - if (all) { - sprintf(buffer, "0x%x", (int) containerPtr->embedded); - Tcl_DStringAppendElement(&dString, buffer); - } else { - Tcl_DStringAppendElement(&dString, "XXX"); - } - } - if (containerPtr->embeddedPtr == NULL) { - Tcl_DStringAppendElement(&dString, ""); - } else { - Tcl_DStringAppendElement(&dString, - containerPtr->embeddedPtr->pathName); - } - Tcl_DStringEndSublist(&dString); + containerPtr = containerPtr->nextPtr) { + Tcl_DStringStartSublist(&dString); + if (containerPtr->parent == None) { + Tcl_DStringAppendElement(&dString, ""); + } else { + if (all) { + sprintf(buffer, "0x%x", (int) containerPtr->parent); + Tcl_DStringAppendElement(&dString, buffer); + } else { + Tcl_DStringAppendElement(&dString, "XXX"); + } + } + if (containerPtr->parentPtr == NULL) { + Tcl_DStringAppendElement(&dString, ""); + } else { + Tcl_DStringAppendElement(&dString, + containerPtr->parentPtr->pathName); + } + if (containerPtr->embedded == None) { + Tcl_DStringAppendElement(&dString, ""); + } else { + if (all) { + sprintf(buffer, "0x%x", (int) containerPtr->embedded); + Tcl_DStringAppendElement(&dString, buffer); + } else { + Tcl_DStringAppendElement(&dString, "XXX"); + } + } + if (containerPtr->embeddedPtr == NULL) { + Tcl_DStringAppendElement(&dString, ""); + } else { + Tcl_DStringAppendElement(&dString, + containerPtr->embeddedPtr->pathName); + } + Tcl_DStringEndSublist(&dString); } Tcl_DStringResult(interp, &dString); return TCL_OK; @@ -687,29 +681,29 @@ TkpTestembedCmd( * * TkpRedirectKeyEvent -- * - * This procedure is invoked when a key press or release event - * arrives for an application that does not believe it owns the - * input focus. This can happen because of embedding; for example, - * X can send an event to an embedded application when the real - * focus window is in the container application and is an ancestor - * of the container. This procedure's job is to forward the event - * back to the application where it really belongs. + * This procedure is invoked when a key press or release event + * arrives for an application that does not believe it owns the + * input focus. This can happen because of embedding; for example, + * X can send an event to an embedded application when the real + * focus window is in the container application and is an ancestor + * of the container. This procedure's job is to forward the event + * back to the application where it really belongs. * * Results: - * None. + * None. * * Side effects: - * The event may get sent to a different application. + * The event may get sent to a different application. * *---------------------------------------------------------------------- */ void TkpRedirectKeyEvent( - TkWindow *winPtr, /* Window to which the event was originally - * reported. */ - XEvent *eventPtr) /* X event to redirect (should be KeyPress - * or KeyRelease). */ + TkWindow *winPtr, /* Window to which the event was originally + * reported. */ + XEvent *eventPtr) /* X event to redirect (should be KeyPress + * or KeyRelease). */ { } @@ -718,24 +712,24 @@ TkpRedirectKeyEvent( * * TkpGetOtherWindow -- * - * If both the container and embedded window are in the same - * process, this procedure will return either one, given the other. + * If both the container and embedded window are in the same + * process, this procedure will return either one, given the other. * * Results: - * If winPtr is a container, the return value is the token for the - * embedded window, and vice versa. If the "other" window isn't in - * this process, NULL is returned. + * If winPtr is a container, the return value is the token for the + * embedded window, and vice versa. If the "other" window isn't in + * this process, NULL is returned. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ TkWindow * TkpGetOtherWindow( - TkWindow *winPtr) /* Tk's structure for a container or - * embedded window. */ + TkWindow *winPtr) /* Tk's structure for a container or + * embedded window. */ { Container *containerPtr; @@ -745,47 +739,48 @@ TkpGetOtherWindow( */ if (!(winPtr->flags & TK_BOTH_HALVES)) { - return NULL; + return NULL; } - + for (containerPtr = firstContainerPtr; containerPtr != NULL; - containerPtr = containerPtr->nextPtr) { - if (containerPtr->embeddedPtr == winPtr) { - return containerPtr->parentPtr; - } else if (containerPtr->parentPtr == winPtr) { - return containerPtr->embeddedPtr; - } + containerPtr = containerPtr->nextPtr) { + if (containerPtr->embeddedPtr == winPtr) { + return containerPtr->parentPtr; + } else if (containerPtr->parentPtr == winPtr) { + return containerPtr->embeddedPtr; + } } return NULL; } + /* *---------------------------------------------------------------------- * * EmbeddedEventProc -- * - * This procedure is invoked by the Tk event dispatcher when various - * useful events are received for a window that is embedded in - * another application. + * This procedure is invoked by the Tk event dispatcher when various + * useful events are received for a window that is embedded in + * another application. * * Results: - * None. + * None. * * Side effects: - * Our internal state gets cleaned up when an embedded window is - * destroyed. + * Our internal state gets cleaned up when an embedded window is + * destroyed. * *---------------------------------------------------------------------- */ static void EmbeddedEventProc(clientData, eventPtr) - ClientData clientData; /* Token for container window. */ - XEvent *eventPtr; /* ResizeRequest event. */ + ClientData clientData; /* Token for container window. */ + XEvent *eventPtr; /* ResizeRequest event. */ { TkWindow *winPtr = (TkWindow *) clientData; if (eventPtr->type == DestroyNotify) { - EmbedWindowDeleted(winPtr); + EmbedWindowDeleted(winPtr); } } @@ -794,28 +789,28 @@ EmbeddedEventProc(clientData, eventPtr) * * ContainerEventProc -- * - * This procedure is invoked by the Tk event dispatcher when various - * useful events are received for the children of a container - * window. It forwards relevant information, such as geometry - * requests, from the events into the container's application. + * This procedure is invoked by the Tk event dispatcher when various + * useful events are received for the children of a container + * window. It forwards relevant information, such as geometry + * requests, from the events into the container's application. * - * NOTE: on the Mac, only the DestroyNotify branch is ever taken. - * We don't synthesize the other events. + * NOTE: on the Mac, only the DestroyNotify branch is ever taken. + * We don't synthesize the other events. * * Results: - * None. + * None. * * Side effects: - * Depends on the event. For example, when ConfigureRequest events - * occur, geometry information gets set for the container window. + * Depends on the event. For example, when ConfigureRequest events + * occur, geometry information gets set for the container window. * *---------------------------------------------------------------------- */ static void ContainerEventProc(clientData, eventPtr) - ClientData clientData; /* Token for container window. */ - XEvent *eventPtr; /* ResizeRequest event. */ + ClientData clientData; /* Token for container window. */ + XEvent *eventPtr; /* ResizeRequest event. */ { TkWindow *winPtr = (TkWindow *) clientData; Container *containerPtr; @@ -828,67 +823,67 @@ ContainerEventProc(clientData, eventPtr) */ errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1, - -1, -1, (Tk_ErrorProc *) NULL, (ClientData) NULL); + -1, -1, (Tk_ErrorProc *) NULL, (ClientData) NULL); /* * Find the Container structure associated with the parent window. */ for (containerPtr = firstContainerPtr; - containerPtr->parent != eventPtr->xmaprequest.parent; - containerPtr = containerPtr->nextPtr) { - if (containerPtr == NULL) { - Tcl_Panic("ContainerEventProc couldn't find Container record"); - } + containerPtr->parent != eventPtr->xmaprequest.parent; + containerPtr = containerPtr->nextPtr) { + if (containerPtr == NULL) { + Tcl_Panic("ContainerEventProc couldn't find Container record"); + } } if (eventPtr->type == CreateNotify) { - /* - * A new child window has been created in the container. Record - * its id in the Container structure (if more than one child is - * created, just remember the last one and ignore the earlier - * ones). - */ - - containerPtr->embedded = eventPtr->xcreatewindow.window; + /* + * A new child window has been created in the container. Record + * its id in the Container structure (if more than one child is + * created, just remember the last one and ignore the earlier + * ones). + */ + + containerPtr->embedded = eventPtr->xcreatewindow.window; } else if (eventPtr->type == ConfigureRequest) { - if ((eventPtr->xconfigurerequest.x != 0) - || (eventPtr->xconfigurerequest.y != 0)) { - /* - * The embedded application is trying to move itself, which - * isn't legal. At this point, the window hasn't actually - * moved, but we need to send it a ConfigureNotify event to - * let it know that its request has been denied. If the - * embedded application was also trying to resize itself, a - * ConfigureNotify will be sent by the geometry management - * code below, so we don't need to do anything. Otherwise, - * generate a synthetic event. - */ - - if ((eventPtr->xconfigurerequest.width == winPtr->changes.width) - && (eventPtr->xconfigurerequest.height - == winPtr->changes.height)) { - EmbedSendConfigure(containerPtr); - } - } - EmbedGeometryRequest(containerPtr, - eventPtr->xconfigurerequest.width, - eventPtr->xconfigurerequest.height); + if ((eventPtr->xconfigurerequest.x != 0) + || (eventPtr->xconfigurerequest.y != 0)) { + /* + * The embedded application is trying to move itself, which + * isn't legal. At this point, the window hasn't actually + * moved, but we need to send it a ConfigureNotify event to + * let it know that its request has been denied. If the + * embedded application was also trying to resize itself, a + * ConfigureNotify will be sent by the geometry management + * code below, so we don't need to do anything. Otherwise, + * generate a synthetic event. + */ + + if ((eventPtr->xconfigurerequest.width == winPtr->changes.width) + && (eventPtr->xconfigurerequest.height + == winPtr->changes.height)) { + EmbedSendConfigure(containerPtr); + } + } + EmbedGeometryRequest(containerPtr, + eventPtr->xconfigurerequest.width, + eventPtr->xconfigurerequest.height); } else if (eventPtr->type == MapRequest) { - /* - * The embedded application's map request was ignored and simply - * passed on to us, so we have to map the window for it to appear - * on the screen. - */ - - XMapWindow(eventPtr->xmaprequest.display, - eventPtr->xmaprequest.window); + /* + * The embedded application's map request was ignored and simply + * passed on to us, so we have to map the window for it to appear + * on the screen. + */ + + XMapWindow(eventPtr->xmaprequest.display, + eventPtr->xmaprequest.window); } else if (eventPtr->type == DestroyNotify) { - /* - * The embedded application is gone. Destroy the container window. - */ + /* + * The embedded application is gone. Destroy the container window. + */ - Tk_DestroyWindow((Tk_Window) winPtr); + Tk_DestroyWindow((Tk_Window) winPtr); } Tk_DeleteErrorHandler(errHandler); } @@ -898,47 +893,47 @@ ContainerEventProc(clientData, eventPtr) * * EmbedStructureProc -- * - * This procedure is invoked by the Tk event dispatcher when - * a container window owned by this application gets resized - * (and also at several other times that we don't care about). - * This procedure reflects the size change in the embedded - * window that corresponds to the container. + * This procedure is invoked by the Tk event dispatcher when + * a container window owned by this application gets resized + * (and also at several other times that we don't care about). + * This procedure reflects the size change in the embedded + * window that corresponds to the container. * * Results: - * None. + * None. * * Side effects: - * The embedded window gets resized to match the container. + * The embedded window gets resized to match the container. * *---------------------------------------------------------------------- */ static void EmbedStructureProc(clientData, eventPtr) - ClientData clientData; /* Token for container window. */ - XEvent *eventPtr; /* ResizeRequest event. */ + ClientData clientData; /* Token for container window. */ + XEvent *eventPtr; /* ResizeRequest event. */ { Container *containerPtr = (Container *) clientData; Tk_ErrorHandler errHandler; if (eventPtr->type == ConfigureNotify) { - if (containerPtr->embedded != None) { - /* - * Ignore errors, since the embedded application could have - * deleted its window. - */ - - errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1, - -1, -1, (Tk_ErrorProc *) NULL, (ClientData) NULL); - Tk_MoveResizeWindow((Tk_Window) containerPtr->embeddedPtr, 0, 0, - (unsigned int) Tk_Width( - (Tk_Window) containerPtr->parentPtr), - (unsigned int) Tk_Height( - (Tk_Window) containerPtr->parentPtr)); - Tk_DeleteErrorHandler(errHandler); - } + if (containerPtr->embedded != None) { + /* + * Ignore errors, since the embedded application could have + * deleted its window. + */ + + errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1, + -1, -1, (Tk_ErrorProc *) NULL, (ClientData) NULL); + Tk_MoveResizeWindow((Tk_Window) containerPtr->embeddedPtr, 0, 0, + (unsigned int) Tk_Width( + (Tk_Window) containerPtr->parentPtr), + (unsigned int) Tk_Height( + (Tk_Window) containerPtr->parentPtr)); + Tk_DeleteErrorHandler(errHandler); + } } else if (eventPtr->type == DestroyNotify) { - EmbedWindowDeleted(containerPtr->parentPtr); + EmbedWindowDeleted(containerPtr->parentPtr); } } @@ -947,33 +942,33 @@ EmbedStructureProc(clientData, eventPtr) * * EmbedActivateProc -- * - * This procedure is invoked by the Tk event dispatcher when - * Activate and Deactivate events occur for a container window owned - * by this application. It is responsible for forwarding an activate - * event down into the embedded toplevel. + * This procedure is invoked by the Tk event dispatcher when + * Activate and Deactivate events occur for a container window owned + * by this application. It is responsible for forwarding an activate + * event down into the embedded toplevel. * * Results: - * None. + * None. * * Side effects: - * The X focus may change. + * The X focus may change. * *---------------------------------------------------------------------- */ static void EmbedActivateProc(clientData, eventPtr) - ClientData clientData; /* Token for container window. */ - XEvent *eventPtr; /* ResizeRequest event. */ + ClientData clientData; /* Token for container window. */ + XEvent *eventPtr; /* ResizeRequest event. */ { Container *containerPtr = (Container *) clientData; - + if (containerPtr->embeddedPtr != NULL) { - if (eventPtr->type == ActivateNotify) { - TkGenerateActivateEvents(containerPtr->embeddedPtr,1); - } else if (eventPtr->type == DeactivateNotify) { - TkGenerateActivateEvents(containerPtr->embeddedPtr,0); - } + if (eventPtr->type == ActivateNotify) { + TkGenerateActivateEvents(containerPtr->embeddedPtr,1); + } else if (eventPtr->type == DeactivateNotify) { + TkGenerateActivateEvents(containerPtr->embeddedPtr,0); + } } } @@ -982,25 +977,25 @@ EmbedActivateProc(clientData, eventPtr) * * EmbedFocusProc -- * - * This procedure is invoked by the Tk event dispatcher when - * FocusIn and FocusOut events occur for a container window owned - * by this application. It is responsible for moving the focus - * back and forth between a container application and an embedded - * application. + * This procedure is invoked by the Tk event dispatcher when + * FocusIn and FocusOut events occur for a container window owned + * by this application. It is responsible for moving the focus + * back and forth between a container application and an embedded + * application. * * Results: - * None. + * None. * * Side effects: - * The X focus may change. + * The X focus may change. * *---------------------------------------------------------------------- */ static void EmbedFocusProc(clientData, eventPtr) - ClientData clientData; /* Token for container window. */ - XEvent *eventPtr; /* ResizeRequest event. */ + ClientData clientData; /* Token for container window. */ + XEvent *eventPtr; /* ResizeRequest event. */ { Container *containerPtr = (Container *) clientData; Display *display; @@ -1008,34 +1003,34 @@ EmbedFocusProc(clientData, eventPtr) if (containerPtr->embeddedPtr != NULL) { display = Tk_Display(containerPtr->parentPtr); - event.xfocus.serial = LastKnownRequestProcessed(display); - event.xfocus.send_event = false; - event.xfocus.display = display; - event.xfocus.mode = NotifyNormal; - event.xfocus.window = containerPtr->embedded; - + event.xfocus.serial = LastKnownRequestProcessed(display); + event.xfocus.send_event = false; + event.xfocus.display = display; + event.xfocus.mode = NotifyNormal; + event.xfocus.window = containerPtr->embedded; + if (eventPtr->type == FocusIn) { - /* - * The focus just arrived at the container. Change the X focus - * to move it to the embedded application, if there is one. - * Ignore X errors that occur during this operation (it's - * possible that the new focus window isn't mapped). - */ - - event.xfocus.detail = NotifyNonlinear; - event.xfocus.type = FocusIn; - - } else if (eventPtr->type == FocusOut) { - /* When the container gets a FocusOut event, it has to tell the embedded app - * that it has lost the focus. - */ - - event.xfocus.type = FocusOut; - event.xfocus.detail = NotifyNonlinear; - } - - Tk_QueueWindowEvent(&event, TCL_QUEUE_MARK); - } + /* + * The focus just arrived at the container. Change the X focus + * to move it to the embedded application, if there is one. + * Ignore X errors that occur during this operation (it's + * possible that the new focus window isn't mapped). + */ + + event.xfocus.detail = NotifyNonlinear; + event.xfocus.type = FocusIn; + + } else if (eventPtr->type == FocusOut) { + /* When the container gets a FocusOut event, it has to tell the embedded app + * that it has lost the focus. + */ + + event.xfocus.type = FocusOut; + event.xfocus.detail = NotifyNonlinear; + } + + Tk_QueueWindowEvent(&event, TCL_QUEUE_MARK); + } } /* @@ -1043,36 +1038,36 @@ EmbedFocusProc(clientData, eventPtr) * * EmbedGeometryRequest -- * - * This procedure is invoked when an embedded application requests - * a particular size. It processes the request (which may or may - * not actually honor the request) and reflects the results back - * to the embedded application. + * This procedure is invoked when an embedded application requests + * a particular size. It processes the request (which may or may + * not actually honor the request) and reflects the results back + * to the embedded application. * - * NOTE: On the Mac, this is a stub, since we don't synthesize - * ConfigureRequest events. + * NOTE: On the Mac, this is a stub, since we don't synthesize + * ConfigureRequest events. * * Results: - * None. + * None. * * Side effects: - * If we deny the child's size change request, a Configure event - * is synthesized to let the child know how big it ought to be. - * Events get processed while we're waiting for the geometry - * managers to do their thing. + * If we deny the child's size change request, a Configure event + * is synthesized to let the child know how big it ought to be. + * Events get processed while we're waiting for the geometry + * managers to do their thing. * *---------------------------------------------------------------------- */ static void EmbedGeometryRequest(containerPtr, width, height) - Container *containerPtr; /* Information about the embedding. */ - int width, height; /* Size that the child has requested. */ + Container *containerPtr; /* Information about the embedding. */ + int width, height; /* Size that the child has requested. */ { TkWindow *winPtr = containerPtr->parentPtr; /* * Forward the requested size into our geometry management hierarchy - * via the container window. We need to send a Configure event back + * via the container window. We need to send a Configure event back * to the embedded application if we decide not to honor its * request; to make this happen, process all idle event handlers * synchronously here (so that the geometry managers have had a @@ -1082,11 +1077,11 @@ EmbedGeometryRequest(containerPtr, width, height) Tk_GeometryRequest((Tk_Window) winPtr, width, height); while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) { - /* Empty loop body. */ + /* Empty loop body. */ } if ((winPtr->changes.width != width) - || (winPtr->changes.height != height)) { - EmbedSendConfigure(containerPtr); + || (winPtr->changes.height != height)) { + EmbedSendConfigure(containerPtr); } } @@ -1095,26 +1090,26 @@ EmbedGeometryRequest(containerPtr, width, height) * * EmbedSendConfigure -- * - * This is currently a stub. It is called to notify an - * embedded application of its current size and location. This - * procedure is called when the embedded application made a - * geometry request that we did not grant, so that the embedded - * application knows that its geometry didn't change after all. - * It is a response to ConfigureRequest events, which we do not - * currently synthesize on the Mac + * This is currently a stub. It is called to notify an + * embedded application of its current size and location. This + * procedure is called when the embedded application made a + * geometry request that we did not grant, so that the embedded + * application knows that its geometry didn't change after all. + * It is a response to ConfigureRequest events, which we do not + * currently synthesize on the Mac * * Results: - * None. + * None. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ static void EmbedSendConfigure(containerPtr) - Container *containerPtr; /* Information about the embedding. */ + Container *containerPtr; /* Information about the embedding. */ { } @@ -1123,28 +1118,28 @@ EmbedSendConfigure(containerPtr) * * EmbedWindowDeleted -- * - * This procedure is invoked when a window involved in embedding - * (as either the container or the embedded application) is - * destroyed. It cleans up the Container structure for the window. + * This procedure is invoked when a window involved in embedding + * (as either the container or the embedded application) is + * destroyed. It cleans up the Container structure for the window. * * Results: - * None. + * None. * * Side effects: - * A Container structure may be freed. + * A Container structure may be freed. * *---------------------------------------------------------------------- */ static void EmbedWindowDeleted(winPtr) - TkWindow *winPtr; /* Tk's information about window that - * was deleted. */ + TkWindow *winPtr; /* Tk's information about window that + * was deleted. */ { Container *containerPtr, *prevPtr; /* - * Find the Container structure for this window. Delete the + * Find the Container structure for this window. Delete the * information about the embedded application and free the container's * record. */ @@ -1152,49 +1147,48 @@ EmbedWindowDeleted(winPtr) prevPtr = NULL; containerPtr = firstContainerPtr; while (1) { - if (containerPtr->embeddedPtr == winPtr) { - - /* - * We also have to destroy our parent, to clean up the container. - * Fabricate an event to do this. - */ - - if (containerPtr->parentPtr != NULL && - containerPtr->parentPtr->flags & TK_BOTH_HALVES) { - XEvent event; - - event.xany.serial = - Tk_Display(containerPtr->parentPtr)->request; - event.xany.send_event = False; - event.xany.display = Tk_Display(containerPtr->parentPtr); - - event.xany.type = DestroyNotify; - event.xany.window = containerPtr->parent; - event.xdestroywindow.event = containerPtr->parent; - Tk_QueueWindowEvent(&event, TCL_QUEUE_HEAD); - - } - - containerPtr->embedded = None; - containerPtr->embeddedPtr = NULL; - - break; - } - if (containerPtr->parentPtr == winPtr) { - containerPtr->parentPtr = NULL; - break; - } - prevPtr = containerPtr; - containerPtr = containerPtr->nextPtr; + if (containerPtr->embeddedPtr == winPtr) { + + /* + * We also have to destroy our parent, to clean up the container. + * Fabricate an event to do this. + */ + + if (containerPtr->parentPtr != NULL && + containerPtr->parentPtr->flags & TK_BOTH_HALVES) { + XEvent event; + + event.xany.serial = + Tk_Display(containerPtr->parentPtr)->request; + event.xany.send_event = False; + event.xany.display = Tk_Display(containerPtr->parentPtr); + + event.xany.type = DestroyNotify; + event.xany.window = containerPtr->parent; + event.xdestroywindow.event = containerPtr->parent; + Tk_QueueWindowEvent(&event, TCL_QUEUE_HEAD); + + } + + containerPtr->embedded = None; + containerPtr->embeddedPtr = NULL; + + break; + } + if (containerPtr->parentPtr == winPtr) { + containerPtr->parentPtr = NULL; + break; + } + prevPtr = containerPtr; + containerPtr = containerPtr->nextPtr; } if ((containerPtr->embeddedPtr == NULL) - && (containerPtr->parentPtr == NULL)) { - if (prevPtr == NULL) { - firstContainerPtr = containerPtr->nextPtr; - } else { - prevPtr->nextPtr = containerPtr->nextPtr; - } - ckfree((char *) containerPtr); + && (containerPtr->parentPtr == NULL)) { + if (prevPtr == NULL) { + firstContainerPtr = containerPtr->nextPtr; + } else { + prevPtr->nextPtr = containerPtr->nextPtr; + } + ckfree((char *) containerPtr); } } - diff --git a/macosx/tkMacOSXEntry.c b/macosx/tkMacOSXEntry.c index bc9a181..f12f624 100644 --- a/macosx/tkMacOSXEntry.c +++ b/macosx/tkMacOSXEntry.c @@ -1,56 +1,59 @@ /* * tkMacOSXEntry.c -- * - * This file implements functions that decode & handle keyboard events - * on MacOS X. + * This file implements the native aqua entry widget. * - * Copyright 2001, Apple Computer, Inc. + * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2006-2007 Daniel A. Steffen * - * The following terms apply to all files originating from Apple - * Computer, Inc. ("Apple") and associated with the software - * unless explicitly disclaimed in individual files. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. * + * The following terms apply to all files originating from Apple + * Computer, Inc. ("Apple") and associated with the software + * unless explicitly disclaimed in individual files. * - * Apple hereby grants permission to use, copy, modify, - * distribute, and license this software and its documentation - * for any purpose, provided that existing copyright notices are - * retained in all copies and that this notice is included - * verbatim in any distributions. No written agreement, license, - * or royalty fee is required for any of the authorized - * uses. Modifications to this software may be copyrighted by - * their authors and need not follow the licensing terms - * described here, provided that the new terms are clearly - * indicated on the first page of each file where they apply. * + * Apple hereby grants permission to use, copy, modify, + * distribute, and license this software and its documentation + * for any purpose, provided that existing copyright notices are + * retained in all copies and that this notice is included + * verbatim in any distributions. No written agreement, license, + * or royalty fee is required for any of the authorized + * uses. Modifications to this software may be copyrighted by + * their authors and need not follow the licensing terms + * described here, provided that the new terms are clearly + * indicated on the first page of each file where they apply. * - * IN NO EVENT SHALL APPLE, THE AUTHORS OR DISTRIBUTORS OF THE - * SOFTWARE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, - * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF - * THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, - * EVEN IF APPLE OR THE AUTHORS HAVE BEEN ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. APPLE, THE AUTHORS AND - * DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS - * SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND APPLE,THE - * AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE - * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * - * GOVERNMENT USE: If you are acquiring this software on behalf - * of the U.S. government, the Government shall have only - * "Restricted Rights" in the software and related documentation - * as defined in the Federal Acquisition Regulations (FARs) in - * Clause 52.227.19 (c) (2). If you are acquiring the software - * on behalf of the Department of Defense, the software shall be - * classified as "Commercial Computer Software" and the - * Government shall have only "Restricted Rights" as defined in - * Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the - * foregoing, the authors grant the U.S. Government and others - * acting in its behalf permission to use and distribute the - * software in accordance with the terms specified in this - * license. + * IN NO EVENT SHALL APPLE, THE AUTHORS OR DISTRIBUTORS OF THE + * SOFTWARE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF + * THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, + * EVEN IF APPLE OR THE AUTHORS HAVE BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. APPLE, THE AUTHORS AND + * DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS + * SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND APPLE,THE + * AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE + * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * - * RCS: @(#) $Id: tkMacOSXEntry.c,v 1.7 2006/09/10 17:06:32 das Exp $ + * GOVERNMENT USE: If you are acquiring this software on behalf + * of the U.S. government, the Government shall have only + * "Restricted Rights" in the software and related documentation + * as defined in the Federal Acquisition Regulations (FARs) in + * Clause 52.227.19 (c) (2). If you are acquiring the software + * on behalf of the Department of Defense, the software shall be + * classified as "Commercial Computer Software" and the + * Government shall have only "Restricted Rights" as defined in + * Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the + * foregoing, the authors grant the U.S. Government and others + * acting in its behalf permission to use and distribute the + * software in accordance with the terms specified in this + * license. + * + * RCS: @(#) $Id: tkMacOSXEntry.c,v 1.8 2007/04/23 21:24:33 das Exp $ */ #include "tkMacOSXInt.h" @@ -65,8 +68,8 @@ static ThemeButtonKind ComputeIncDecParameters (int height, int *width); * ComputeIncDecParameters -- * * This procedure figures out which of the kThemeIncDec - * buttons to use. It also sets width to the width of the - * IncDec button. + * buttons to use. It also sets width to the width of the + * IncDec button. * * Results: * The ThemeButtonKind of the button we should use. @@ -79,45 +82,37 @@ static ThemeButtonKind ComputeIncDecParameters (int height, int *width); static ThemeButtonKind ComputeIncDecParameters (int height, int *width) { - static int version = 0; - - if (version == 0) { - Gestalt(gestaltSystemVersion, (long *) &version); - } - - /* - * The small and mini incDec buttons were introduced in 10.3. - */ - #ifndef kThemeIncDecButtonSmall - #define kThemeIncDecButtonSmall 21 - #endif - #ifndef kThemeIncDecButtonMini - #define kThemeIncDecButtonMini 22 - #endif - - if (version >= 0x1030) { - if (height < 11 || height > 28) { - *width = 0; - return (ThemeButtonKind) 0; - } - - if (height >= 21) { - *width = 13; - return kThemeIncDecButton; - } else if (height >= 18) { - *width = 12; - return kThemeIncDecButtonSmall; - } else { - *width = 11; - return kThemeIncDecButtonMini; - } - } else { - if (height < 21 || height > 28) { - *width = 0; - return (ThemeButtonKind) 0; - } - *width = 13; - return kThemeIncDecButton; +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 + if (1 +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1030 + && &kHIToolboxVersionNumber != NULL + && kHIToolboxVersionNumber >= kHIToolboxVersionNumber10_3 +#endif + ) { + if (height < 11 || height > 28) { + *width = 0; + return (ThemeButtonKind) 0; + } + + if (height >= 21) { + *width = 13; + return kThemeIncDecButton; + } else if (height >= 18) { + *width = 12; + return kThemeIncDecButtonSmall; + } else { + *width = 11; + return kThemeIncDecButtonMini; + } + } else +#endif + { + if (height < 21 || height > 28) { + *width = 0; + return (ThemeButtonKind) 0; + } + *width = 13; + return kThemeIncDecButton; } } @@ -127,11 +122,11 @@ ComputeIncDecParameters (int height, int *width) * TkpDrawEntryBorderAndFocus -- * * This procedure redraws the border of an entry window. - * It overrides the generic border drawing code if the - * entry widget parameters are such that the native widget - * drawing is a good fit. - * This version just returns 1, so platforms that don't - * do special native drawing don't have to implement it. + * It overrides the generic border drawing code if the + * entry widget parameters are such that the native widget + * drawing is a good fit. + * This version just returns 1, so platforms that don't + * do special native drawing don't have to implement it. * * Results: * 1 if it has drawn the border, 0 if not. @@ -145,44 +140,41 @@ int TkpDrawEntryBorderAndFocus(Entry *entryPtr, Drawable d, int isSpinbox) { Rect bounds; - CGrafPtr saveWorld; - GDHandle saveDevice; - GWorldPtr destPort; + TkMacOSXDrawingContext dc; GC bgGC; Tk_Window tkwin = entryPtr->tkwin; ThemeDrawState drawState; int oldWidth = 0; + MacDrawable *macDraw = (MacDrawable *) d; - /* - * I use 6 as the borderwidth. 2 of the 5 go into the actual frame the + /* + * I use 6 as the borderwidth. 2 of the 5 go into the actual frame the * 3 are because the Mac OS Entry widgets leave more space around the * Text than Tk does on X11. */ - - if (entryPtr->borderWidth != MAC_OSX_ENTRY_BORDER - || entryPtr->highlightWidth != MAC_OSX_FOCUS_WIDTH - || entryPtr->relief != MAC_OSX_ENTRY_RELIEF) { - return 0; + + if (entryPtr->borderWidth != MAC_OSX_ENTRY_BORDER + || entryPtr->highlightWidth != MAC_OSX_FOCUS_WIDTH + || entryPtr->relief != MAC_OSX_ENTRY_RELIEF) { + return 0; } - - destPort = TkMacOSXGetDrawablePort(d); /* * For the spinbox, we have to make the entry part smaller by the size - * of the buttons. We also leave 2 pixels to the left (as per the HIG) + * of the buttons. We also leave 2 pixels to the left (as per the HIG) * and space for one pixel to the right, 'cause it makes the buttons look - * nicer. + * nicer. */ - + if (isSpinbox) { - ThemeButtonKind buttonKind; - int incDecWidth; - - oldWidth = Tk_Width(tkwin); - - buttonKind = ComputeIncDecParameters(Tk_Height(tkwin) - - 2 * MAC_OSX_FOCUS_WIDTH, &incDecWidth); - Tk_Width(tkwin) -= incDecWidth + 1; + ThemeButtonKind buttonKind; + int incDecWidth; + + oldWidth = Tk_Width(tkwin); + + buttonKind = ComputeIncDecParameters(Tk_Height(tkwin) + - 2 * MAC_OSX_FOCUS_WIDTH, &incDecWidth); + Tk_Width(tkwin) -= incDecWidth + 1; } /* @@ -190,42 +182,39 @@ TkpDrawEntryBorderAndFocus(Entry *entryPtr, Drawable d, int isSpinbox) * part of the ring, so we have to draw over the edges of the * ring before drawing the focus or the text will peep through. */ - + bgGC = Tk_GCForColor(entryPtr->highlightBgColorPtr, d); TkDrawInsetFocusHighlight(entryPtr->tkwin, bgGC, MAC_OSX_FOCUS_WIDTH, d, 0); - - GetGWorld(&saveWorld, &saveDevice); - SetGWorld(destPort, NULL); - + /* - * Inset the entry Frame by the maximum width of the focus rect, + * Inset the entry Frame by the maximum width of the focus rect, * which is 3 according to the Carbon docs. */ - - bounds.top = MAC_OSX_FOCUS_WIDTH; - bounds.left = MAC_OSX_FOCUS_WIDTH; - bounds.right = Tk_Width(tkwin) - MAC_OSX_FOCUS_WIDTH; - bounds.bottom = Tk_Height(tkwin) - MAC_OSX_FOCUS_WIDTH; + + bounds.left = macDraw->xOff + MAC_OSX_FOCUS_WIDTH; + bounds.top = macDraw->yOff + MAC_OSX_FOCUS_WIDTH; + bounds.right = macDraw->xOff + Tk_Width(tkwin) - MAC_OSX_FOCUS_WIDTH; + bounds.bottom = macDraw->yOff + Tk_Height(tkwin) - MAC_OSX_FOCUS_WIDTH; if (entryPtr->state == STATE_DISABLED) { - drawState = kThemeStateInactive; + drawState = kThemeStateInactive; } else { - drawState = kThemeStateActive; + drawState = kThemeStateActive; } + TkMacOSXSetupDrawingContext(d, NULL, 0, &dc); DrawThemeEditTextFrame(&bounds, drawState); if (entryPtr->flags & GOT_FOCUS) { - /* - * Don't call this if we don't have the focus, because then it - * erases the focus rect to white, but we've already drawn the - * highlightbackground above. - */ + /* + * Don't call this if we don't have the focus, because then it + * erases the focus rect to white, but we've already drawn the + * highlightbackground above. + */ - DrawThemeFocusRect(&bounds, (entryPtr->flags & GOT_FOCUS) != 0); + DrawThemeFocusRect(&bounds, (entryPtr->flags & GOT_FOCUS) != 0); } - SetGWorld(saveWorld, saveDevice); - if (isSpinbox) { - Tk_Width(tkwin) = oldWidth; + Tk_Width(tkwin) = oldWidth; } + TkMacOSXRestoreDrawingContext(&dc); return 1; } /* @@ -234,11 +223,11 @@ TkpDrawEntryBorderAndFocus(Entry *entryPtr, Drawable d, int isSpinbox) * TkpDrawSpinboxButtons -- * * This procedure redraws the buttons of an spinbox widget. - * It overrides the generic button drawing code if the - * spinbox widget parameters are such that the native widget - * drawing is a good fit. - * This version just returns 0, so platforms that don't - * do special native drawing don't have to implement it. + * It overrides the generic button drawing code if the + * spinbox widget parameters are such that the native widget + * drawing is a good fit. + * This version just returns 0, so platforms that don't + * do special native drawing don't have to implement it. * * Results: * 1 if it has drawn the border, 0 if not. @@ -252,7 +241,6 @@ TkpDrawEntryBorderAndFocus(Entry *entryPtr, Drawable d, int isSpinbox) int TkpDrawSpinboxButtons(Spinbox *sbPtr, Drawable d) { - OSStatus err; Rect inBounds; ThemeButtonKind inKind; ThemeButtonDrawInfo inNewInfo; @@ -264,71 +252,65 @@ TkpDrawSpinboxButtons(Spinbox *sbPtr, Drawable d) int height = Tk_Height(tkwin); int buttonHeight = height - 2 * MAC_OSX_FOCUS_WIDTH; int incDecWidth; - CGrafPtr saveWorld; - GDHandle saveDevice; - GWorldPtr destPort; + TkMacOSXDrawingContext dc; XRectangle rects[1]; GC bgGC; + MacDrawable *macDraw = (MacDrawable *) d; /* FIXME RAISED really makes more sense */ if (sbPtr->buRelief != TK_RELIEF_FLAT) { - return 0; + return 0; } - - /* + + /* * The actual sizes of the IncDec button are 21 for the normal, - * 18 for the small and 15 for the mini. But the spinbox still + * 18 for the small and 15 for the mini. But the spinbox still * looks okay if the entry is a little bigger than this, so we * give it a little slop. */ - + inKind = ComputeIncDecParameters(buttonHeight, &incDecWidth); if (inKind == (ThemeButtonKind) 0) { - return 0; + return 0; } - - destPort = TkMacOSXGetDrawablePort(d); - GetGWorld(&saveWorld, &saveDevice); - SetGWorld(destPort, NULL); if (sbPtr->entry.state == STATE_DISABLED) { - inNewInfo.state = kThemeStateInactive; - inNewInfo.value = kThemeButtonOff; + inNewInfo.state = kThemeStateInactive; + inNewInfo.value = kThemeButtonOff; } else if (sbPtr->selElement == SEL_BUTTONUP) { - inNewInfo.state = kThemeStatePressedUp; - inNewInfo.value = kThemeButtonOn; + inNewInfo.state = kThemeStatePressedUp; + inNewInfo.value = kThemeButtonOn; } else if (sbPtr->selElement == SEL_BUTTONDOWN) { - inNewInfo.state = kThemeStatePressedDown; - inNewInfo.value = kThemeButtonOn; + inNewInfo.state = kThemeStatePressedDown; + inNewInfo.value = kThemeButtonOn; } else { - inNewInfo.state = kThemeStateActive; - inNewInfo.value = kThemeButtonOff; + inNewInfo.state = kThemeStateActive; + inNewInfo.value = kThemeButtonOff; } - + inNewInfo.adornment = kThemeAdornmentNone; - inBounds.left = Tk_Width(tkwin) - incDecWidth - 1; - inBounds.right = Tk_Width(tkwin) - 1; - inBounds.top = MAC_OSX_FOCUS_WIDTH; - inBounds.bottom = Tk_Height(tkwin) - MAC_OSX_FOCUS_WIDTH; - + inBounds.left = macDraw->xOff + Tk_Width(tkwin) - incDecWidth - 1; + inBounds.right = macDraw->xOff + Tk_Width(tkwin) - 1; + inBounds.top = macDraw->yOff + MAC_OSX_FOCUS_WIDTH; + inBounds.bottom = macDraw->yOff + Tk_Height(tkwin) - MAC_OSX_FOCUS_WIDTH; + /* We had to make the entry part of the window smaller so that we - * wouldn't overdraw the spin buttons with the focus highlight. SO + * wouldn't overdraw the spin buttons with the focus highlight. So * now we have to draw the highlightbackground. */ - + bgGC = Tk_GCForColor(sbPtr->entry.highlightBgColorPtr, d); rects[0].x = inBounds.left; rects[0].y = 0; rects[0].width = Tk_Width(tkwin); rects[0].height = Tk_Height(tkwin); XFillRectangles(Tk_Display(tkwin), d, bgGC, rects, 1); - - err = DrawThemeButton (&inBounds, inKind, &inNewInfo, inPrevInfo, - inEraseProc, inLabelProc, inUserData); - - SetGWorld(saveWorld, saveDevice); + TkMacOSXSetupDrawingContext(d, NULL, 0, &dc); + ChkErr(DrawThemeButton, &inBounds, inKind, &inNewInfo, inPrevInfo, + inEraseProc, inLabelProc, inUserData); + TkMacOSXRestoreDrawingContext(&dc); return 1; } diff --git a/macosx/tkMacOSXEvent.c b/macosx/tkMacOSXEvent.c index b94606e..82aea7a 100644 --- a/macosx/tkMacOSXEvent.c +++ b/macosx/tkMacOSXEvent.c @@ -1,109 +1,110 @@ -/* +/* * tkMacOSXEvent.c -- * - * This file contains the basic Mac OS X Event handling routines. + * This file contains the basic Mac OS X Event handling routines. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. - * Copyright (c) 2005-2006 Daniel A. Steffen + * Copyright (c) 2005-2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXEvent.c,v 1.14 2007/04/21 19:06:38 hobbs Exp $ + * RCS: @(#) $Id: tkMacOSXEvent.c,v 1.15 2007/04/23 21:24:33 das Exp $ */ #include "tkMacOSXInt.h" #include "tkMacOSXEvent.h" #include "tkMacOSXDebug.h" + /* *---------------------------------------------------------------------- * * TkMacOSXFlushWindows -- * - * This routine flushes all the Carbon windows of the application. It - * is called by the setup procedure for the Tcl/Carbon event source. + * This routine flushes all the Carbon windows of the application. It + * is called by the setup procedure for the Tcl/Carbon event source. * * Results: - * None. + * None. * * Side effects: - * Flushes all Carbon windows + * Flushes all Carbon windows * *---------------------------------------------------------------------- */ MODULE_SCOPE void -TkMacOSXFlushWindows () +TkMacOSXFlushWindows (void) { WindowRef wRef = GetWindowList(); - + while (wRef) { - CGrafPtr portPtr = GetWindowPort(wRef); - if (QDIsPortBuffered(portPtr)) { - QDFlushPortBuffer(portPtr, NULL); - } - wRef = GetNextWindow(wRef); + CGrafPtr portPtr = GetWindowPort(wRef); + if (QDIsPortBuffered(portPtr)) { + QDFlushPortBuffer(portPtr, NULL); + } + wRef = GetNextWindow(wRef); } } -/* +/* *---------------------------------------------------------------------- - * + * * TkMacOSXProcessEvent -- - * - * This dispatches a filtered Carbon event to the appropriate handler * - * Note on MacEventStatus.stopProcessing: Please be conservative in the - * individual handlers and don't assume the event is fully handled - * unless you *really* need to ensure that other handlers don't see the - * event anymore. Some OS manager or library might be interested in - * events even after they are already handled on the Tk level. + * This dispatches a filtered Carbon event to the appropriate handler * - * Results: - * 0 on success - * -1 on failure + * Note on MacEventStatus.stopProcessing: Please be conservative in the + * individual handlers and don't assume the event is fully handled + * unless you *really* need to ensure that other handlers don't see the + * event anymore. Some OS manager or library might be interested in + * events even after they are already handled on the Tk level. + * + * Results: + * 0 on success + * -1 on failure * * Side effects: - * Converts a Carbon event to a Tk event - * + * Converts a Carbon event to a Tk event + * *---------------------------------------------------------------------- */ -MODULE_SCOPE int -TkMacOSXProcessEvent(TkMacOSXEvent * eventPtr, MacEventStatus * statusPtr) +MODULE_SCOPE int +TkMacOSXProcessEvent( + TkMacOSXEvent *eventPtr, + MacEventStatus *statusPtr) { switch (eventPtr->eClass) { - case kEventClassMouse: - TkMacOSXProcessMouseEvent(eventPtr, statusPtr); - break; - case kEventClassWindow: - TkMacOSXProcessWindowEvent(eventPtr, statusPtr); - break; - case kEventClassKeyboard: - TkMacOSXProcessKeyboardEvent(eventPtr, statusPtr); - break; - case kEventClassApplication: - TkMacOSXProcessApplicationEvent(eventPtr, statusPtr); - break; - case kEventClassMenu: - TkMacOSXProcessMenuEvent(eventPtr, statusPtr); - break; - case kEventClassCommand: - TkMacOSXProcessCommandEvent(eventPtr, statusPtr); - break; - default: -#ifdef TK_MAC_DEBUG - { - char buf [256]; - fprintf(stderr, - "Unrecognised event : %s\n", - TkMacOSXCarbonEventToAscii(eventPtr->eventRef, buf)); - } -#endif - break; - } + case kEventClassMouse: + TkMacOSXProcessMouseEvent(eventPtr, statusPtr); + break; + case kEventClassWindow: + TkMacOSXProcessWindowEvent(eventPtr, statusPtr); + break; + case kEventClassKeyboard: + TkMacOSXProcessKeyboardEvent(eventPtr, statusPtr); + break; + case kEventClassApplication: + TkMacOSXProcessApplicationEvent(eventPtr, statusPtr); + break; + case kEventClassAppearance: + TkMacOSXProcessAppearanceEvent(eventPtr, statusPtr); + break; + case kEventClassMenu: + TkMacOSXProcessMenuEvent(eventPtr, statusPtr); + break; + case kEventClassCommand: + TkMacOSXProcessCommandEvent(eventPtr, statusPtr); + break; + default: { + TkMacOSXDbgMsg("Unrecognised event: %s", + TkMacOSXCarbonEventToAscii(eventPtr->eventRef)); + break; + } + } return 0; } @@ -112,51 +113,81 @@ TkMacOSXProcessEvent(TkMacOSXEvent * eventPtr, MacEventStatus * statusPtr) * * TkMacOSXProcessMenuEvent -- * - * This routine processes the event in eventPtr, and - * generates the appropriate Tk events from it. + * This routine processes the event in eventPtr, and + * generates the appropriate Tk events from it. * * Results: - * True if event(s) are generated - false otherwise. + * True if event(s) are generated - false otherwise. * * Side effects: - * Additional events may be place on the Tk event queue. + * Additional events may be place on the Tk event queue. * *---------------------------------------------------------------------- */ MODULE_SCOPE int -TkMacOSXProcessMenuEvent(TkMacOSXEvent *eventPtr, MacEventStatus * statusPtr) +TkMacOSXProcessMenuEvent( + TkMacOSXEvent *eventPtr, + MacEventStatus *statusPtr) { - int menuContext; - OSStatus status; + int menuContext; + OSStatus err; switch (eventPtr->eKind) { case kEventMenuBeginTracking: case kEventMenuEndTracking: + case kEventMenuOpening: + case kEventMenuTargetItem: break; default: return 0; break; } - status = GetEventParameter(eventPtr->eventRef, - kEventParamMenuContext, - typeUInt32, NULL, - sizeof(menuContext), NULL, - &menuContext); - if (status == noErr && (menuContext & kMenuContextMenuBar)) { - static int oldMode = TCL_SERVICE_ALL; - if (eventPtr->eKind == kEventMenuBeginTracking) { - oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); - TkMacOSXClearMenubarActive(); - - /* - * Handle -postcommand - */ - - TkMacOSXPreprocessMenu(); - } else { - Tcl_SetServiceMode(oldMode); - } + err = ChkErr(GetEventParameter, eventPtr->eventRef, kEventParamMenuContext, + typeUInt32, NULL, sizeof(menuContext), NULL, &menuContext); + if (err == noErr && ((menuContext & kMenuContextMenuBarTracking) || + (menuContext & kMenuContextPopUpTracking))) { + switch (eventPtr->eKind) { + MenuRef menu; + + case kEventMenuBeginTracking: + TkMacOSXClearMenubarActive(); + + /* + * Handle -postcommand + */ + + TkMacOSXPreprocessMenu(); + TkMacOSXTrackingLoop(1); + break; + case kEventMenuEndTracking: + TkMacOSXTrackingLoop(0); + break; + case kEventMenuOpening: + err = ChkErr(GetEventParameter, eventPtr->eventRef, + kEventParamDirectObject, typeMenuRef, NULL, + sizeof(menu), NULL, &menu); + if (err == noErr) { + TkMacOSXClearActiveMenu(menu); + return TkMacOSXGenerateParentMenuSelectEvent(menu); + } + break; + case kEventMenuTargetItem: + err = ChkErr(GetEventParameter, eventPtr->eventRef, + kEventParamDirectObject, typeMenuRef, NULL, + sizeof(menu), NULL, &menu); + if (err == noErr) { + MenuItemIndex index; + + err = ChkErr(GetEventParameter, eventPtr->eventRef, + kEventParamMenuItemIndex, typeMenuItemIndex, NULL, + sizeof(index), NULL, &index); + if (err == noErr) { + return TkMacOSXGenerateMenuSelectEvent(menu, index); + } + } + break; + } } return 0; } @@ -166,24 +197,26 @@ TkMacOSXProcessMenuEvent(TkMacOSXEvent *eventPtr, MacEventStatus * statusPtr) * * TkMacOSXProcessCommandEvent -- * - * This routine processes the event in eventPtr, and - * generates the appropriate Tk events from it. + * This routine processes the event in eventPtr, and + * generates the appropriate Tk events from it. * * Results: - * True if event(s) are generated - false otherwise. + * True if event(s) are generated - false otherwise. * * Side effects: - * Additional events may be place on the Tk event queue. + * Additional events may be place on the Tk event queue. * *---------------------------------------------------------------------- */ MODULE_SCOPE int -TkMacOSXProcessCommandEvent(TkMacOSXEvent *eventPtr, MacEventStatus * statusPtr) +TkMacOSXProcessCommandEvent( + TkMacOSXEvent *eventPtr, + MacEventStatus * statusPtr) { - HICommand command; - int menuContext; - OSStatus status; + HICommand command; + int menuContext; + OSStatus err; switch (eventPtr->eKind) { case kEventCommandProcess: @@ -193,19 +226,15 @@ TkMacOSXProcessCommandEvent(TkMacOSXEvent *eventPtr, MacEventStatus * statusPtr) return 0; break; } - status = GetEventParameter(eventPtr->eventRef, - kEventParamDirectObject, - typeHICommand, NULL, - sizeof(command), NULL, - &command); - if (status == noErr && (command.attributes & kHICommandFromMenu)) { + err = ChkErr(GetEventParameter, eventPtr->eventRef, + kEventParamDirectObject, typeHICommand, NULL, sizeof(command), + NULL, &command); + if (err == noErr && (command.attributes & kHICommandFromMenu)) { if (eventPtr->eKind == kEventCommandProcess) { - status = GetEventParameter(eventPtr->eventRef, - kEventParamMenuContext, - typeUInt32, NULL, - sizeof(menuContext), NULL, - &menuContext); - if (status == noErr && (menuContext & kMenuContextMenuBar) && + err = ChkErr(GetEventParameter, eventPtr->eventRef, + kEventParamMenuContext, typeUInt32, NULL, + sizeof(menuContext), NULL, &menuContext); + if (err == noErr && (menuContext & kMenuContextMenuBar) && (menuContext & kMenuContextMenuBarTracking)) { TkMacOSXHandleMenuSelect(GetMenuID(command.menu.menuRef), command.menu.menuItemIndex, @@ -215,15 +244,15 @@ TkMacOSXProcessCommandEvent(TkMacOSXEvent *eventPtr, MacEventStatus * statusPtr) } else { Tcl_CmdInfo dummy; if (command.commandID == kHICommandPreferences && eventPtr->interp) { - if (Tcl_GetCommandInfo(eventPtr->interp, + if (Tcl_GetCommandInfo(eventPtr->interp, "::tk::mac::ShowPreferences", &dummy)) { - if (!IsMenuItemEnabled(command.menu.menuRef, + if (!IsMenuItemEnabled(command.menu.menuRef, command.menu.menuItemIndex)) { EnableMenuItem(command.menu.menuRef, command.menu.menuItemIndex); } } else { - if (IsMenuItemEnabled(command.menu.menuRef, + if (IsMenuItemEnabled(command.menu.menuRef, command.menu.menuItemIndex)) { DisableMenuItem(command.menu.menuRef, command.menu.menuItemIndex); @@ -236,56 +265,3 @@ TkMacOSXProcessCommandEvent(TkMacOSXEvent *eventPtr, MacEventStatus * statusPtr) } return 0; } - -/* - *---------------------------------------------------------------------- - * - * TkMacOSXReceiveAndProcessEvent -- - * - * This receives a carbon event and converts it to a Tk event - * - * Results: - * 0 on success - * Mac OS error number on failure - * - * Side effects: - * This receives the next Carbon event and converts it to the - * appropriate Tk event - * - *---------------------------------------------------------------------- - */ - -MODULE_SCOPE OSStatus -TkMacOSXReceiveAndProcessEvent() -{ - static EventTargetRef targetRef = NULL; - EventRef eventRef; - OSStatus err; - - /* - * This is a poll, since we have already counted the events coming - * into this routine, and are guaranteed to have one waiting. - */ - - err = ReceiveNextEvent(0, NULL, kEventDurationNoWait, true, &eventRef); - if (err == noErr) { - if (!targetRef) { - targetRef = GetEventDispatcherTarget(); - } - TkMacOSXStartTclEventLoopCarbonTimer(); - err = SendEventToEventTarget(eventRef,targetRef); - TkMacOSXStopTclEventLoopCarbonTimer(); -#ifdef TK_MAC_DEBUG - if (err != noErr && err != eventLoopTimedOutErr - && err != eventNotHandledErr - ) { - char buf [256]; - fprintf(stderr, - "RCNE SendEventToEventTarget (%s) failed, %d\n", - TkMacOSXCarbonEventToAscii(eventRef, buf), (int)err); - } -#endif - ReleaseEvent(eventRef); - } - return err; -} diff --git a/macosx/tkMacOSXEvent.h b/macosx/tkMacOSXEvent.h index 9c5f583..7fcb503 100644 --- a/macosx/tkMacOSXEvent.h +++ b/macosx/tkMacOSXEvent.h @@ -2,55 +2,59 @@ * tkMacOSXEvent.h -- * * Declarations of Macintosh specific functions for implementing the - * Mac OS X Notifier. + * Mac OS X Notifier. * - * Copyright 2001, Apple Computer, Inc. + * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2005-2007 Daniel A. Steffen * - * The following terms apply to all files originating from Apple - * Computer, Inc. ("Apple") and associated with the software - * unless explicitly disclaimed in individual files. + * See the file "license.terms" for information on usage and redistribution of + * this file, and for a DISCLAIMER OF ALL WARRANTIES. * + * The following terms apply to all files originating from Apple + * Computer, Inc. ("Apple") and associated with the software + * unless explicitly disclaimed in individual files. * - * Apple hereby grants permission to use, copy, modify, - * distribute, and license this software and its documentation - * for any purpose, provided that existing copyright notices are - * retained in all copies and that this notice is included - * verbatim in any distributions. No written agreement, license, - * or royalty fee is required for any of the authorized - * uses. Modifications to this software may be copyrighted by - * their authors and need not follow the licensing terms - * described here, provided that the new terms are clearly - * indicated on the first page of each file where they apply. * + * Apple hereby grants permission to use, copy, modify, + * distribute, and license this software and its documentation + * for any purpose, provided that existing copyright notices are + * retained in all copies and that this notice is included + * verbatim in any distributions. No written agreement, license, + * or royalty fee is required for any of the authorized + * uses. Modifications to this software may be copyrighted by + * their authors and need not follow the licensing terms + * described here, provided that the new terms are clearly + * indicated on the first page of each file where they apply. * - * IN NO EVENT SHALL APPLE, THE AUTHORS OR DISTRIBUTORS OF THE - * SOFTWARE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, - * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF - * THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, - * EVEN IF APPLE OR THE AUTHORS HAVE BEEN ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. APPLE, THE AUTHORS AND - * DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS - * SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND APPLE,THE - * AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE - * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * - * GOVERNMENT USE: If you are acquiring this software on behalf - * of the U.S. government, the Government shall have only - * "Restricted Rights" in the software and related documentation - * as defined in the Federal Acquisition Regulations (FARs) in - * Clause 52.227.19 (c) (2). If you are acquiring the software - * on behalf of the Department of Defense, the software shall be - * classified as "Commercial Computer Software" and the - * Government shall have only "Restricted Rights" as defined in - * Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the - * foregoing, the authors grant the U.S. Government and others - * acting in its behalf permission to use and distribute the - * software in accordance with the terms specified in this - * license. + * IN NO EVENT SHALL APPLE, THE AUTHORS OR DISTRIBUTORS OF THE + * SOFTWARE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF + * THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, + * EVEN IF APPLE OR THE AUTHORS HAVE BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. APPLE, THE AUTHORS AND + * DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS + * SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND APPLE,THE + * AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE + * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * - * RCS: @(#) $Id: tkMacOSXEvent.h,v 1.11 2006/07/20 06:25:19 das Exp $ + * GOVERNMENT USE: If you are acquiring this software on behalf + * of the U.S. government, the Government shall have only + * "Restricted Rights" in the software and related documentation + * as defined in the Federal Acquisition Regulations (FARs) in + * Clause 52.227.19 (c) (2). If you are acquiring the software + * on behalf of the Department of Defense, the software shall be + * classified as "Commercial Computer Software" and the + * Government shall have only "Restricted Rights" as defined in + * Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the + * foregoing, the authors grant the U.S. Government and others + * acting in its behalf permission to use and distribute the + * software in accordance with the terms specified in this + * license. + * + * RCS: @(#) $Id: tkMacOSXEvent.h,v 1.12 2007/04/23 21:24:33 das Exp $ */ #ifndef _TKMACEVENT @@ -72,37 +76,32 @@ typedef struct { typedef struct { EventRef eventRef; UInt32 eClass; /* Defines the class of event : see CarbonEvents.h */ - UInt32 eKind; /* Defines the kind of the event : see CarbonEvents.h */ + UInt32 eKind; /* Defines the kind of the event : see CarbonEvents.h */ Tcl_Interp *interp; /* Interp to handle events in */ + EventHandlerCallRef callRef; } TkMacOSXEvent; -MODULE_SCOPE OSStatus TkMacOSXReceiveAndProcessEvent(); -MODULE_SCOPE void TkMacOSXFlushWindows(); -MODULE_SCOPE int TkMacOSXProcessEvent(TkMacOSXEvent *eventPtr, - MacEventStatus *statusPtr); +MODULE_SCOPE void TkMacOSXFlushWindows(void); +MODULE_SCOPE int TkMacOSXProcessEvent(TkMacOSXEvent *eventPtr, + MacEventStatus *statusPtr); MODULE_SCOPE int TkMacOSXProcessMouseEvent(TkMacOSXEvent *e, - MacEventStatus *statusPtr); + MacEventStatus *statusPtr); MODULE_SCOPE int TkMacOSXProcessWindowEvent(TkMacOSXEvent *e, - MacEventStatus *statusPtr); + MacEventStatus *statusPtr); MODULE_SCOPE int TkMacOSXProcessKeyboardEvent(TkMacOSXEvent *e, - MacEventStatus *statusPtr); + MacEventStatus *statusPtr); MODULE_SCOPE int TkMacOSXProcessApplicationEvent(TkMacOSXEvent *e, - MacEventStatus *statusPtr); + MacEventStatus *statusPtr); +MODULE_SCOPE int TkMacOSXProcessAppearanceEvent(TkMacOSXEvent *e, + MacEventStatus *statusPtr); MODULE_SCOPE int TkMacOSXProcessMenuEvent(TkMacOSXEvent *e, - MacEventStatus *statusPtr); + MacEventStatus *statusPtr); MODULE_SCOPE int TkMacOSXProcessCommandEvent(TkMacOSXEvent *e, - MacEventStatus *statusPtr); + MacEventStatus *statusPtr); MODULE_SCOPE int TkMacOSXKeycodeToUnicode( - UniChar * uniChars, int maxChars, - EventKind eKind, - UInt32 keycode, UInt32 modifiers, - UInt32 * deadKeyStatePtr); -MODULE_SCOPE OSStatus TkMacOSXStartTclEventLoopCarbonTimer(); -MODULE_SCOPE OSStatus TkMacOSXStopTclEventLoopCarbonTimer(); - -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 -/* Define constants only available on Mac OS X 10.3 or later */ -#define kEventAppAvailableWindowBoundsChanged 110 -#endif + UniChar * uniChars, int maxChars, + EventKind eKind, + UInt32 keycode, UInt32 modifiers, + UInt32 * deadKeyStatePtr); #endif diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c index 2f81ae5..1a4a399 100644 --- a/macosx/tkMacOSXFont.c +++ b/macosx/tkMacOSXFont.c @@ -1,10 +1,11 @@ /* * tkMacOSXFont.c -- * - * Contains the Macintosh implementation of the platform-independant - * font package interface. This version uses ATSU instead of Quickdraw. + * Contains the Macintosh implementation of the platform-independant + * font package interface. This version uses ATSU instead of Quickdraw. * * Copyright 2002-2004 Benjamin Riefenstahl, Benjamin.Riefenstahl@epost.de + * Copyright (c) 2006-2007 Daniel A. Steffen * * Some functions were originally copied verbatim from the QuickDraw version * of tkMacOSXFont.c, which had these copyright notices: @@ -16,7 +17,6 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * * Todos: * * - Get away from Font Manager and Quickdraw functions as much as possible, @@ -26,39 +26,31 @@ * instead of just assuming that they are the same. * * - Get a second font register going for fonts that are not assigned to a - * font family by the OS. On my system I have 27 fonts of that type, + * font family by the OS. On my system I have 27 fonts of that type, * Hebrew, Arabic and Hindi fonts that actually come with the system. * FMGetFontFamilyInstanceFromFont() returns -981 (kFMInvalidFontFamilyErr) * for these and they are not listed when enumerating families, but they - * are when enumerating fonts directly. The problem that the OS sees may - * be that at least some of them do not contain any Latin characters. Note + * are when enumerating fonts directly. The problem that the OS sees may + * be that at least some of them do not contain any Latin characters. Note * that such fonts can not be used for controls, because controls * definitely require a family id (this assertion needs testing). * - * RCS: @(#) $Id: tkMacOSXFont.c,v 1.23 2007/04/21 19:06:38 hobbs Exp $ + * RCS: @(#) $Id: tkMacOSXFont.c,v 1.24 2007/04/23 21:24:33 das Exp $ */ #include "tkMacOSXInt.h" #include "tkMacOSXFont.h" /* -#ifdef TK_MAC_DEBUG +#ifdef TK_MAC_DEBUG #define TK_MAC_DEBUG_FONTS #endif */ -/* Define macros only available on Mac OS X 10.3 or later */ -#ifndef FixedToInt -#define FixedToInt(a) ((short)(((Fixed)(a) + fixed1/2) >> 16)) -#endif -#ifndef IntToFixed -#define IntToFixed(a) ((Fixed)(a) << 16) -#endif - /* - * Problem: The sum of two parts is not the same as the whole. In particular + * Problem: The sum of two parts is not the same as the whole. In particular * the width of two separately measured strings will usually be larger than - * the width of them pasted together. Tk has a design bug here, because it + * the width of them pasted together. Tk has a design bug here, because it * generally assumes that this kind of arithmetic works. * To workaround this, #define TK_MAC_COALESCE_LINE to 1 below, we then avoid * lines that tremble and shiver while the cursor passes through them by @@ -68,17 +60,45 @@ */ #define TK_MAC_COALESCE_LINE 0 -typedef TkMacOSXFont MacFont; -typedef TkMacOSXFontDrawingContext DrawingContext; +/* + * The following structure represents our Macintosh-specific implementation + * of a font object. + */ + +typedef struct { + TkFont font; /* Stuff used by generic font package. Must + * be first in structure. */ + + /* + * The ATSU view of the font and other text properties. Used for drawing + * and measuring. + */ + + ATSUFontID atsuFontId; /* == FMFont. */ + ATSUTextLayout atsuLayout; /* ATSU layout object, representing the whole + * text that ATSU sees with some option + * bits. */ + ATSUStyle atsuStyle; /* ATSU style object, representing a run of + * text with the same properties. */ + + /* + * The QuickDraw view of the font. Used to configure controls. + */ + + FMFontFamily qdFont; /* == FMFontFamilyId, Carbon replacement for + * QD face numbers. */ + short qdSize; /* Font size in points. */ + short qdStyle; /* QuickDraw style bits. */ +} MacFont; /* - * Information about font families, initialized at startup time. Font + * Information about font families, initialized at startup time. Font * families are described by a mapping from UTF-8 names to MacOS font family - * IDs. The whole list is kept as the sorted array "familyList", allocated + * IDs. The whole list is kept as the sorted array "familyList", allocated * with ckrealloc(). * * Note: This would have been easier, if we could just have used Tcl hash - * arrays. Unfortunately there seems to be no pre-packaged + * arrays. Unfortunately there seems to be no pre-packaged * non-case-sensitive version of that available. */ @@ -89,137 +109,121 @@ typedef struct { static MacFontFamily * familyList = NULL; static int - familyListNextFree = 0, /* The next free slot in familyList. */ - familyListMaxValid = 0, /* The top of the sorted area. */ - familyListSize = 0; /* The size of the whole array. */ + familyListNextFree = 0, /* The next free slot in familyList. */ + familyListMaxValid = 0, /* The top of the sorted area. */ + familyListSize = 0; /* The size of the whole array. */ /* * A simple one-shot sub-allocator for fast and efficient allocation of - * strings. Used by the familyList array for the names. These strings are - * only allocated once at startup and never freed. If you ever need to + * strings. Used by the familyList array for the names. These strings are + * only allocated once at startup and never freed. If you ever need to * re-initialize this, you can just ckfree() all the StringBlocks in the list * and start over. */ -#define STRING_BLOCK_MAX (1024-8) /* Make sizeof(StringBlock) == - * 1024. */ +#define STRING_BLOCK_MAX (1024-8) /* Make sizeof(StringBlock) == + * 1024. */ typedef struct StringBlock { - struct StringBlock * next; /* Starting from "stringMemory" these - * blocks form a linked list. */ - int nextFree; /* Top of the used area in the - * "strings" member. */ - char strings[STRING_BLOCK_MAX]; /* The actual memory managed here. */ + struct StringBlock *next; /* Starting from "stringMemory" these + * blocks form a linked list. */ + int nextFree; /* Top of the used area in the + * "strings" member. */ + char strings[STRING_BLOCK_MAX]; /* The actual memory managed here. */ } StringBlock; -static StringBlock * stringMemory = NULL; - +static StringBlock *stringMemory = NULL; #if TK_MAC_COALESCE_LINE -static Tcl_DString currentLine; /* The current line as seen so far. This - * contains a Tcl_UniChar DString. */ +static Tcl_DString currentLine; /* The current line as seen so far. This + * contains a Tcl_UniChar DString. */ static int - currentY = -1, /* The Y position (row in pixels) of the - * current line. */ - currentLeft = -1, /* The left edge (pixels) of the current - * line. */ - currentRight = -1; /* The right edge (pixels) of the current - * line. */ -static const MacFont * currentFontPtr = NULL; - /* The font of the current line. */ + currentY = -1, /* The Y position (row in pixels) of the + * current line. */ + currentLeft = -1, /* The left edge (pixels) of the current + * line. */ + currentRight = -1; /* The right edge (pixels) of the current + * line. */ +static const MacFont *currentFontPtr = NULL; + /* The font of the current line. */ #endif /* TK_MAC_COALESCE_LINE */ static int antialiasedTextEnabled; /* - * The names for our two "native" fonts. + * The names for our "native" fonts. */ -#define SYSTEMFONT_NAME "system" -#define APPLFONT_NAME "application" +#define SYSTEMFONT_NAME "system" +#define APPLFONT_NAME "application" +#define MENUITEMFONT_NAME "menu" /* * Procedures used only in this file. */ +static void LayoutSetString(const MacFont *fontPtr, + const TkMacOSXDrawingContext *drawingContextPtr, + const UniChar * uchars, int ulen); + /* * The actual workers. */ -static void MacFontDrawText( - const MacFont * fontPtr, - const char * source, int numBytes, - int rangeStart, int rangeLength, - int x, int y); -static int MeasureStringWidth( - const MacFont * fontPtr, - int start, int end); +static int MeasureStringWidth(const MacFont *fontPtr, int start, int end); #if TK_MAC_COALESCE_LINE -static const Tcl_UniChar * UpdateLineBuffer( - const MacFont * fontPtr, - const DrawingContext * drawingContextPtr, - const char * source, int numBytes, - int x, int y, - int * offset); +static const Tcl_UniChar *UpdateLineBuffer(const MacFont *fontPtr, + const TkMacOSXDrawingContext *drawingContextPtr, const char *source, + int numBytes, int x, int y, int * offset); #endif /* TK_MAC_COALESCE_LINE */ /* * Initialization and setup of a font data structure. */ -static void InitFont( - Tk_Window tkwin, - FMFontFamily familyId, const char * familyName, - int size, int qdStyle, MacFont * fontPtr); -static void InitATSUObjects( - FMFontFamily familyId, - short qdsize, short qdStyle, - ATSUFontID * fontIdPtr, - ATSUTextLayout * layoutPtr, ATSUStyle * stylePtr); -static void InitATSUStyle( - ATSUFontID fontId, short ptSize, short qdStyle, - ATSUStyle style); -static void SetFontFeatures( - ATSUFontID fontId, int fixed, - ATSUStyle style); -static void AdjustFontHeight( - MacFont * fontPtr); -static void InitATSULayout( - const DrawingContext * drawingContextPtr, - ATSUTextLayout layout, int fixed); -static void ReleaseFont( - MacFont * fontPtr); +static void InitFont(Tk_Window tkwin, FMFontFamily familyId, + const char *familyName, int size, int qdStyle, MacFont *fontPtr); +static void InitATSUObjects(FMFontFamily familyId, short qdsize, short qdStyle, + ATSUFontID *fontIdPtr, ATSUTextLayout *layoutPtr, ATSUStyle *stylePtr); +static void InitATSUStyle(ATSUFontID fontId, short ptSize, short qdStyle, + ATSUStyle style); +static void SetFontFeatures(ATSUFontID fontId, int fixed, ATSUStyle style); +static void AdjustFontHeight(MacFont *fontPtr); +static void InitATSULayout(const TkMacOSXDrawingContext *drawingContextPtr, + ATSUTextLayout layout, int fixed); +static void ReleaseFont(MacFont *fontPtr); /* * Finding fonts by name. */ -static const MacFontFamily * FindFontFamilyOrAlias( - const char * name); -static const MacFontFamily * FindFontFamilyOrAliasOrFallback( - const char * name); +static const MacFontFamily *FindFontFamilyOrAlias(const char *name); +static const MacFontFamily *FindFontFamilyOrAliasOrFallback(const char *name); /* * Doing interesting things with font families and fonts. */ static void InitFontFamilies(void); -static OSStatus GetFontFamilyName( - FMFontFamily fontFamily, char * name, int numBytes); +static OSStatus GetFontFamilyName(FMFontFamily fontFamily, char *name, + int numBytes); /* * Accessor functions and internal utilities for the font family list. */ -static const MacFontFamily * AddFontFamily( - const char * name, FMFontFamily familyId); -static const MacFontFamily * FindFontFamily(const char * name); -static Tcl_Obj * EnumFontFamilies(void); +static const MacFontFamily *AddFontFamily(const char *name, + FMFontFamily familyId); +static const MacFontFamily *FindFontFamily(const char *name); +static Tcl_Obj *EnumFontFamilies(void); static OSStatus FontFamilyEnumCallback(ATSFontFamilyRef family, void *refCon); static void SortFontFamilies(void); -static int CompareFontFamilies(const void * vp1, const void * vp2); -static const char * AddString(const char * in); +static int CompareFontFamilies(const void *vp1, const void *vp2); +static const char *AddString(const char *in); +static OSStatus GetThemeFontAndFamily(const ThemeFontID themeFontId, + FMFontFamily *fontFamily, unsigned char *fontName, SInt16 *fontSize, + Style *fontStyle); /* @@ -227,33 +231,60 @@ static const char * AddString(const char * in); * * TkpFontPkgInit -- * - * This procedure is called when an application is created. It - * initializes all the structures that are used by the - * platform-dependant code on a per application basis. + * This procedure is called when an application is created. It + * initializes all the structures that are used by the + * platform-dependant code on a per application basis. * * Results: - * None. + * None. * * Side effects: - * Initialization of variables local to this file. + * Initialization of variables local to this file. * *------------------------------------------------------------------------- */ void TkpFontPkgInit( - TkMainInfo * mainPtr) /* The application being created. */ + TkMainInfo *mainPtr) /* The application being created. */ { InitFontFamilies(); #if TK_MAC_COALESCE_LINE Tcl_DStringInit(¤tLine); #endif +} + +/* + *--------------------------------------------------------------------------- + * + * GetThemeFontAndFamily -- + * + * Wrapper around the GetThemeFont and FMGetFontFamilyFromName APIs. + * + *--------------------------------------------------------------------------- + */ -#ifdef TK_MAC_DEBUG_FONTS - fprintf(stderr, "tkMacOSXFont.c (ATSU version) intialized " - "(" __TIME__ ")\n"); -#endif +OSStatus +GetThemeFontAndFamily( + const ThemeFontID themeFontId, + FMFontFamily* fontFamily, + unsigned char *fontName, + SInt16 *fontSize, + Style *fontStyle) +{ + OSStatus err = ChkErr(GetThemeFont, themeFontId, smSystemScript, fontName, + fontSize, fontStyle); + + if (err == noErr) { + *fontFamily = FMGetFontFamilyFromName(fontName); + if (*fontFamily == kInvalidFontFamily) { + err = kFMInvalidFontFamilyErr; + TkMacOSXDbgMsg("FMGetFontFamilyFromName failed."); + } + } + + return err; } /* @@ -261,45 +292,56 @@ TkpFontPkgInit( * * TkpGetNativeFont -- * - * Map a platform-specific native font name to a TkFont. + * Map a platform-specific native font name to a TkFont. * * Results: - * The return value is a pointer to a TkFont that represents the - * native font. If a native font by the given name could not be - * found, the return value is NULL. + * The return value is a pointer to a TkFont that represents the + * native font. If a native font by the given name could not be + * found, the return value is NULL. * - * Every call to this procedure returns a new TkFont structure, even - * if the name has already been seen before. The caller should call - * TkpDeleteFont() when the font is no longer needed. + * Every call to this procedure returns a new TkFont structure, even + * if the name has already been seen before. The caller should call + * TkpDeleteFont() when the font is no longer needed. * - * The caller is responsible for initializing the memory associated - * with the generic TkFont when this function returns and releasing - * the contents of the generics TkFont before calling TkpDeleteFont(). + * The caller is responsible for initializing the memory associated + * with the generic TkFont when this function returns and releasing + * the contents of the generics TkFont before calling TkpDeleteFont(). * * Side effects: - * None. + * None. * *--------------------------------------------------------------------------- */ TkFont * TkpGetNativeFont( - Tk_Window tkwin, /* For display where font will be used. */ - const char * name) /* Platform-specific font name. */ + Tk_Window tkwin, /* For display where font will be used. */ + const char * name) /* Platform-specific font name. */ { - FMFontFamily familyId; + ThemeFontID themeFontId; + FMFontFamily fontFamily; + Str255 fontName; + SInt16 fontSize; + Style fontStyle; MacFont * fontPtr; if (strcmp(name, SYSTEMFONT_NAME) == 0) { - familyId = GetSysFont(); + themeFontId = kThemeSystemFont; } else if (strcmp(name, APPLFONT_NAME) == 0) { - familyId = GetAppFont(); + themeFontId = kThemeApplicationFont; + } else if (strcmp(name, MENUITEMFONT_NAME) == 0) { + themeFontId = kThemeMenuItemFont; } else { - return NULL; + return NULL; } + if (GetThemeFontAndFamily(themeFontId, &fontFamily, fontName, &fontSize, + &fontStyle) != noErr) { + return NULL; + } + CopyPascalStringToC(fontName, (char*)fontName); fontPtr = (MacFont *) ckalloc(sizeof(MacFont)); - InitFont(tkwin, familyId, NULL, 0, 0, fontPtr); + InitFont(tkwin, fontFamily, (char*)fontName, fontSize, fontStyle, fontPtr); return (TkFont *) fontPtr; } @@ -309,74 +351,74 @@ TkpGetNativeFont( * * TkpGetFontFromAttributes -- * - * Given a desired set of attributes for a font, find a font with the - * closest matching attributes. + * Given a desired set of attributes for a font, find a font with the + * closest matching attributes. * * Results: - * The return value is a pointer to a TkFont that represents the font - * with the desired attributes. If a font with the desired attributes - * could not be constructed, some other font will be substituted - * automatically. + * The return value is a pointer to a TkFont that represents the font + * with the desired attributes. If a font with the desired attributes + * could not be constructed, some other font will be substituted + * automatically. * - * Every call to this procedure returns a new TkFont structure, even - * if the specified attributes have already been seen before. The - * caller should call TkpDeleteFont() to free the platform- specific - * data when the font is no longer needed. + * Every call to this procedure returns a new TkFont structure, even + * if the specified attributes have already been seen before. The + * caller should call TkpDeleteFont() to free the platform- specific + * data when the font is no longer needed. * - * The caller is responsible for initializing the memory associated - * with the generic TkFont when this function returns and releasing - * the contents of the generic TkFont before calling TkpDeleteFont(). + * The caller is responsible for initializing the memory associated + * with the generic TkFont when this function returns and releasing + * the contents of the generic TkFont before calling TkpDeleteFont(). * * Side effects: - * None. + * None. * *--------------------------------------------------------------------------- */ TkFont * TkpGetFontFromAttributes( - TkFont * tkFontPtr, /* If non-NULL, store the information in this - * existing TkFont structure, rather than - * allocating a new structure to hold the font; - * the existing contents of the font will be - * released. If NULL, a new TkFont structure is - * allocated. */ - Tk_Window tkwin, /* For display where font will be used. */ - const TkFontAttributes * faPtr) - /* Set of attributes to match. */ + TkFont *tkFontPtr, /* If non-NULL, store the information in this + * existing TkFont structure, rather than + * allocating a new structure to hold the + * font; the existing contents of the font + * will be released. If NULL, a new TkFont + * structure is allocated. */ + Tk_Window tkwin, /* For display where font will be used. */ + const TkFontAttributes *faPtr) + /* Set of attributes to match. */ { short qdStyle; FMFontFamily familyId; - const char * name; - const MacFontFamily * familyPtr; - MacFont * fontPtr; + const char *name; + const MacFontFamily *familyPtr; + MacFont *fontPtr; familyId = GetAppFont(); name = NULL; qdStyle = 0; if (faPtr->family != NULL) { - familyPtr = FindFontFamilyOrAliasOrFallback(faPtr->family); - if (familyPtr != NULL) { - name = familyPtr->name; - familyId = familyPtr->familyId; - } + familyPtr = FindFontFamilyOrAliasOrFallback(faPtr->family); + if (familyPtr != NULL) { + name = familyPtr->name; + familyId = familyPtr->familyId; + } } if (faPtr->weight != TK_FW_NORMAL) { - qdStyle |= bold; + qdStyle |= bold; } if (faPtr->slant != TK_FS_ROMAN) { - qdStyle |= italic; + qdStyle |= italic; } if (faPtr->underline) { - qdStyle |= underline; + qdStyle |= underline; } if (tkFontPtr == NULL) { - fontPtr = (MacFont *) ckalloc(sizeof(MacFont)); + fontPtr = (MacFont *) ckalloc(sizeof(MacFont)); } else { - fontPtr = (MacFont *) tkFontPtr; - ReleaseFont(fontPtr); + fontPtr = (MacFont *) tkFontPtr; + ReleaseFont(fontPtr); } InitFont(tkwin, familyId, name, faPtr->size, qdStyle, fontPtr); @@ -388,23 +430,23 @@ TkpGetFontFromAttributes( * * TkpDeleteFont -- * - * Called to release a font allocated by TkpGetNativeFont() or - * TkpGetFontFromAttributes(). The caller should have already - * released the fields of the TkFont that are used exclusively by the - * generic TkFont code. + * Called to release a font allocated by TkpGetNativeFont() or + * TkpGetFontFromAttributes(). The caller should have already + * released the fields of the TkFont that are used exclusively by the + * generic TkFont code. * * Results: - * TkFont is deallocated. + * TkFont is deallocated. * * Side effects: - * None. + * None. * *--------------------------------------------------------------------------- */ void TkpDeleteFont( - TkFont * tkFontPtr) /* Token of font to be deleted. */ + TkFont *tkFontPtr) /* Token of font to be deleted. */ { ReleaseFont((MacFont *) tkFontPtr); } @@ -414,25 +456,25 @@ TkpDeleteFont( * * TkpGetFontFamilies -- * - * Return information about the font families that are available on - * the display of the given window. + * Return information about the font families that are available on + * the display of the given window. * * Results: - * Modifies interp's result object to hold a list of all the available - * font families. + * Modifies interp's result object to hold a list of all the available + * font families. * * Side effects: - * None. + * None. * *--------------------------------------------------------------------------- */ void TkpGetFontFamilies( - Tcl_Interp * interp, /* Interp to hold result. */ - Tk_Window tkwin) /* For display to query. */ + Tcl_Interp *interp, /* Interp to hold result. */ + Tk_Window tkwin) /* For display to query. */ { - Tcl_SetObjResult(interp,EnumFontFamilies()); + Tcl_SetObjResult(interp, EnumFontFamilies()); } /* @@ -440,26 +482,26 @@ TkpGetFontFamilies( * * TkpGetSubFonts -- * - * A function used by the testing package for querying the actual - * screen fonts that make up a font object. + * A function used by the testing package for querying the actual + * screen fonts that make up a font object. * * Results: - * Modifies interp's result object to hold a list containing the names - * of the screen fonts that make up the given font object. + * Modifies interp's result object to hold a list containing the names + * of the screen fonts that make up the given font object. * * Side effects: - * None. + * None. * *------------------------------------------------------------------------- */ void TkpGetSubFonts( - Tcl_Interp * interp, /* Interp to hold result. */ - Tk_Font tkfont) /* Font object to query. */ + Tcl_Interp *interp, /* Interp to hold result. */ + Tk_Font tkfont) /* Font object to query. */ { /* We don't know much about our fallback fonts, ATSU does all that for - * us. We could use ATSUMatchFont to implement this function. But as + * us. We could use ATSUMatchFont to implement this function. But as * the information is only used for testing, such an effort seems not * very useful. */ } @@ -469,35 +511,35 @@ TkpGetSubFonts( * * TkpGetFontAttrsForChar -- * - * Retrieve the font attributes of the actual font used to render a - * given character. + * Retrieve the font attributes of the actual font used to render a + * given character. * * Results: - * None. + * None. * * Side effects: - * The font attributes are stored in *faPtr. + * The font attributes are stored in *faPtr. * *---------------------------------------------------------------------- */ void TkpGetFontAttrsForChar( - Tk_Window tkwin, /* Window on the font's display */ - Tk_Font tkfont, /* Font to query */ - Tcl_UniChar c, /* Character of interest */ - TkFontAttributes* faPtr) /* Output: Font attributes */ + Tk_Window tkwin, /* Window on the font's display */ + Tk_Font tkfont, /* Font to query */ + Tcl_UniChar c, /* Character of interest */ + TkFontAttributes* faPtr) /* Output: Font attributes */ { - TkMacOSXFont* fontPtr = (TkMacOSXFont*) tkfont; + const MacFont * fontPtr = (const MacFont *) tkfont; UniChar uchar = c; - DrawingContext drawingContext; + TkMacOSXDrawingContext drawingContext; OSStatus err; ATSUFontID fontId; UniCharArrayOffset changedOffset; UniCharCount changedLength; /* - * Most of the attributes are just copied from the base font. This + * Most of the attributes are just copied from the base font. This * assumes that all fonts can have all attributes. */ @@ -507,202 +549,172 @@ TkpGetFontAttrsForChar( * But the name of the actual font may still differ, so we activate the * string as an ATSU layout and ask ATSU about the fallback. */ + TkMacOSXSetupDrawingContext(Tk_WindowId(tkwin), NULL, 1, &drawingContext); -#if TK_MAC_USE_QUARZ - TkMacOSXQuarzStartDraw(&drawingContext); -#endif - - TkMacOSXLayoutSetString(fontPtr, &drawingContext, &uchar, 1); + LayoutSetString(fontPtr, &drawingContext, &uchar, 1); fontId = fontPtr->atsuFontId; err = ATSUMatchFontsToText( - fontPtr->atsuLayout, 0, 1, - &fontId, &changedOffset, &changedLength); -#ifdef TK_MAC_DEBUG_FONTS + fontPtr->atsuLayout, 0, 1, + &fontId, &changedOffset, &changedLength); if (err != kATSUFontsMatched && err != noErr) { - fprintf(stderr, "TkpGetFontAttrsForChar: " - "Can't match \\u%04X\n", - (unsigned) c); + TkMacOSXDbgMsg("Can't match \\u%04X", (unsigned) c); } -#endif if (err == kATSUFontsMatched) { - - /* - * A fallback was used and the actual font is in fontId. Determine - * the name. - */ - - FMFontFamily fontFamilyId; - FMFontStyle fontStyle; - int i; - - err = FMGetFontFamilyInstanceFromFont( - fontId, &fontFamilyId, &fontStyle); -#ifdef TK_MAC_DEBUG_FONTS - if (err != noErr) { - fprintf(stderr, "FMGetFontFamilyInstanceFromFont: Error %d\n", - (int) err); - } -#endif - - if (err == noErr) { - - /* - * Find the canonical name in our global list. - */ - - for (i=0; ifamily = familyList[i].name; - break; - } - } -#ifdef TK_MAC_DEBUG_FONTS - if (i >= familyListMaxValid) { - fprintf(stderr, "TkpGetFontAttrsForChar: " - "Can't find font %d for \\u%04X\n", - (int) fontFamilyId, (unsigned) c); - } -#endif - } + /* + * A fallback was used and the actual font is in fontId. Determine + * the name. + */ + + FMFontFamily fontFamilyId; + FMFontStyle fontStyle; + int i; + + err = ChkErr(FMGetFontFamilyInstanceFromFont, fontId, &fontFamilyId, + &fontStyle); + if (err == noErr) { + /* + * Find the canonical name in our global list. + */ + + for (i=0; ifamily = familyList[i].name; + break; + } + } + if (i >= familyListMaxValid) { + TkMacOSXDbgMsg("Can't find font %d for \\u%04X", fontFamilyId, + (unsigned) c); + } + } } -#if TK_MAC_USE_QUARZ - TkMacOSXQuarzEndDraw(&drawingContext); -#endif + TkMacOSXRestoreDrawingContext(&drawingContext); } /* *--------------------------------------------------------------------------- * - * Tk_MeasureChars -- + * Tk_MeasureChars -- * - * Determine the number of characters from the string that will fit in - * the given horizontal span. The measurement is done under the - * assumption that Tk_DrawChars() will be used to actually display the - * characters. + * Determine the number of characters from the string that will fit in + * the given horizontal span. The measurement is done under the + * assumption that Tk_DrawChars() will be used to actually display the + * characters. * - * With ATSUI we need the line context to do this right, so we have the - * actual implementation in TkpMeasureCharsInContext(). + * With ATSUI we need the line context to do this right, so we have the + * actual implementation in TkpMeasureCharsInContext(). * * Results: - * - * The return value is the number of bytes from source that fit into the - * span that extends from 0 to maxLength. *lengthPtr is filled with the - * x-coordinate of the right edge of the last character that did fit. + * The return value is the number of bytes from source that fit into the + * span that extends from 0 to maxLength. *lengthPtr is filled with the + * x-coordinate of the right edge of the last character that did fit. * * Side effects: - * - * None. + * None. * * Todo: - * - * Effects of the "flags" parameter are untested. + * Effects of the "flags" parameter are untested. * *--------------------------------------------------------------------------- */ int Tk_MeasureChars( - Tk_Font tkfont, /* Font in which characters will be drawn. */ - const char * source, /* UTF-8 string to be displayed. Need not be - * '\0' terminated. */ - int numBytes, /* Maximum number of bytes to consider from - * source string. */ - int maxLength, /* If >= 0, maxLength specifies the longest - * permissible line length; don't consider any - * character that would cross this x-position. - * If < 0, then line length is unbounded and the - * flags argument is ignored. */ - int flags, /* Various flag bits OR-ed together: - * TK_PARTIAL_OK means include the last char - * which only partially fit on this line. - * TK_WHOLE_WORDS means stop on a word boundary, - * if possible. TK_AT_LEAST_ONE means return at - * least one character even if no characters - * fit. */ - int * lengthPtr) /* Filled with x-location just after the - * terminating character. */ + Tk_Font tkfont, /* Font in which characters will be drawn. */ + const char *source, /* UTF-8 string to be displayed. Need not be + * '\0' terminated. */ + int numBytes, /* Maximum number of bytes to consider from + * source string. */ + int maxLength, /* If >= 0, maxLength specifies the longest + * permissible line length; don't consider any + * character that would cross this x-position. + * If < 0, then line length is unbounded and + * the flags argument is ignored. */ + int flags, /* Various flag bits OR-ed together: + * TK_PARTIAL_OK means include the last char + * which only partially fit on this line. + * TK_WHOLE_WORDS means stop on a word + * boundary, if possible. TK_AT_LEAST_ONE + * means return at least one character even if + * no characters fit. */ + int *lengthPtr) /* Filled with x-location just after the + * terminating character. */ { - return TkpMeasureCharsInContext( - tkfont, source, numBytes, 0, numBytes, maxLength, flags, lengthPtr); + return TkpMeasureCharsInContext(tkfont, source, numBytes, 0, numBytes, + maxLength, flags, lengthPtr); } /* *--------------------------------------------------------------------------- * - * TkpMeasureCharsInContext -- + * TkpMeasureCharsInContext -- * - * Determine the number of bytes from the string that will fit in the - * given horizontal span. The measurement is done under the assumption - * that TkpDrawCharsInContext() will be used to actually display the - * characters. + * Determine the number of bytes from the string that will fit in the + * given horizontal span. The measurement is done under the assumption + * that TkpDrawCharsInContext() will be used to actually display the + * characters. * - * This one is almost the same as Tk_MeasureChars(), but with access to - * all the characters on the line for context. + * This one is almost the same as Tk_MeasureChars(), but with access to + * all the characters on the line for context. * * Results: - * The return value is the number of bytes from source that - * fit into the span that extends from 0 to maxLength. *lengthPtr is - * filled with the x-coordinate of the right edge of the last - * character that did fit. + * The return value is the number of bytes from source that + * fit into the span that extends from 0 to maxLength. *lengthPtr is + * filled with the x-coordinate of the right edge of the last + * character that did fit. * * Side effects: - * None. + * None. * *--------------------------------------------------------------------------- */ int TkpMeasureCharsInContext( - Tk_Font tkfont, /* Font in which characters will be drawn. */ - const char * source, /* UTF-8 string to be displayed. Need not be - * '\0' terminated. */ - int numBytes, /* Maximum number of bytes to consider from - * source string in all. */ - int rangeStart, /* Index of first byte to measure. */ - int rangeLength, /* Length of range to measure in bytes. */ - int maxLength, /* If >= 0, maxLength specifies the longest - * permissible line length; don't consider any - * character that would cross this x-position. - * If < 0, then line length is unbounded and the - * flags argument is ignored. */ - int flags, /* Various flag bits OR-ed together: - * TK_PARTIAL_OK means include the last char - * which only partially fits on this line. - * TK_WHOLE_WORDS means stop on a word boundary, - * if possible. - * TK_AT_LEAST_ONE means return at least one - * character (or at least the first partial word - * in case TK_WHOLE_WORDS is also set) even if no - * characters (words) fit. - * TK_ISOLATE_END means that the last character - * should not be considered in context with the - * rest of the string (used for breaking - * lines). */ - int * lengthPtr) /* Filled with x-location just after the - * terminating character. */ + Tk_Font tkfont, /* Font in which characters will be drawn. */ + const char * source, /* UTF-8 string to be displayed. Need not be + * '\0' terminated. */ + int numBytes, /* Maximum number of bytes to consider from + * source string in all. */ + int rangeStart, /* Index of first byte to measure. */ + int rangeLength, /* Length of range to measure in bytes. */ + int maxLength, /* If >= 0, maxLength specifies the longest + * permissible line length; don't consider any + * character that would cross this x-position. + * If < 0, then line length is unbounded and + * the flags argument is ignored. */ + int flags, /* Various flag bits OR-ed together: + * TK_PARTIAL_OK means include the last char + * which only partially fits on this line. + * TK_WHOLE_WORDS means stop on a word + * boundary, if possible. TK_AT_LEAST_ONE + * means return at least one character (or at + * least the first partial word in case + * TK_WHOLE_WORDS is also set) even if no + * characters (words) fit. TK_ISOLATE_END + * means that the last character should not be + * considered in context with the rest of the + * string (used for breaking lines). */ + int *lengthPtr) /* Filled with x-location just after the + * terminating character. */ { - const MacFont * fontPtr = (const MacFont *) tkfont; - int curX = -1; - int curByte = 0; - UniChar * uchars; + const MacFont *fontPtr = (const MacFont *) tkfont; + int curX = -1, curByte = 0; + UniChar *uchars; int ulen, urstart, urlen, urend; Tcl_DString ucharBuffer; - DrawingContext drawingContext; - /* * Sanity checks. */ - if ((rangeStart < 0) || ((rangeStart+rangeLength) > numBytes)) { -#ifdef TK_MAC_DEBUG_FONTS - fprintf(stderr, "MeasureChars: bad parameters\n"); -#endif - *lengthPtr = 0; - return 0; + if (rangeStart < 0 || (rangeStart+rangeLength) > numBytes) { + TkMacOSXDbgMsg("Bad parameters"); + *lengthPtr = 0; + return 0; } /* @@ -710,284 +722,243 @@ TkpMeasureCharsInContext( */ if (rangeLength == 0 || (maxLength == 0 && !(flags & TK_AT_LEAST_ONE))) { -#ifdef TK_MAC_DEBUG_FONTS - fflush(stdout); - fprintf(stderr, "measure: '%.*s', empty\n", - rangeLength, source+rangeStart); - fflush(stderr); -#endif - *lengthPtr = 0; - return 0; + *lengthPtr = 0; + return 0; } -#if TK_MAC_USE_QUARZ - TkMacOSXQuarzStartDraw(&drawingContext); -#endif - Tcl_DStringInit(&ucharBuffer); uchars = Tcl_UtfToUniCharDString(source, numBytes, &ucharBuffer); ulen = Tcl_DStringLength(&ucharBuffer) / sizeof(Tcl_UniChar); - TkMacOSXLayoutSetString(fontPtr, &drawingContext, uchars, ulen); + LayoutSetString(fontPtr, NULL, uchars, ulen); urstart = Tcl_NumUtfChars(source, rangeStart); urlen = Tcl_NumUtfChars(source+rangeStart,rangeLength); urend = urstart + urlen; if (maxLength < 0) { - - curX = MeasureStringWidth(fontPtr, urstart, urend); - curByte = rangeLength; - + curX = MeasureStringWidth(fontPtr, urstart, urend); + curByte = rangeLength; } else { - - UniCharArrayOffset offset = 0; - OSStatus err; - - /* - * Have some upper limit on the size actually used. - */ - - if (maxLength > 32767) { - maxLength = 32767; - } - - offset = urstart; - err = noErr; - - if (maxLength > 1) { - - /* - * Let the system do some work by calculating a line break. - * - * Somehow ATSUBreakLine seems to assume that it needs at least - * one pixel padding. So we add one to the limit. Note also - * that ATSUBreakLine sometimes runs into an endless loop when - * the third parameter is equal or less than IntToFixed(2), so we - * need at least IntToFixed(3) (at least that's the current state - * of my knowledge). - */ - - err = ATSUBreakLine( - fontPtr->atsuLayout, - urstart, - IntToFixed(maxLength+1), - false, /* !iUseAsSoftLineBreak */ - &offset); - - /* - * There is no way to signal an error from this routine, so we - * use predefined offset=urstart and otherwise ignore the - * possibility. - */ + UniCharArrayOffset offset = 0; + OSStatus err; + + /* + * Have some upper limit on the size actually used. + */ + + if (maxLength > 32767) { + maxLength = 32767; + } + + offset = urstart; + err = noErr; + + if (maxLength > 1) { + /* + * Let the system do some work by calculating a line break. + * + * Somehow ATSUBreakLine seems to assume that it needs at least + * one pixel padding. So we add one to the limit. Note also + * that ATSUBreakLine sometimes runs into an endless loop when + * the third parameter is equal or less than IntToFixed(2), so we + * need at least IntToFixed(3) (at least that's the current state + * of my knowledge). + */ + + err = ATSUBreakLine(fontPtr->atsuLayout, urstart, + IntToFixed(maxLength+1), false, /* !iUseAsSoftLineBreak */ + &offset); + + /* + * There is no way to signal an error from this routine, so we + * use predefined offset=urstart and otherwise ignore the + * possibility. + */ + + if ((err != noErr) && (err != kATSULineBreakInWord)) { + TkMacOSXDbgMsg("ATSUBreakLine failed: %ld for '%.*s'", err, + rangeLength, source+rangeStart); + } #ifdef TK_MAC_DEBUG_FONTS - if ((err != noErr) && (err != kATSULineBreakInWord)) { - fprintf(stderr, "ATSUBreakLine(): Error %d for '%.*s'\n", - (int) err, rangeLength, source+rangeStart); - } + TkMacOSXDbgMsg("measure: '%.*s', break offset=%ld, errcode=%ld", + rangeLength, source+rangeStart, offset, err); #endif -#ifdef TK_MAC_DEBUG_FONTS - fprintf(stderr, "measure: '%.*s', break offset=%d, errcode=%d\n", - rangeLength, source+rangeStart, (int) offset, (int) err); -#endif - - /* - * ATSUBreakLine includes the whitespace that separates words, - * but we don't want that. Besides, ATSUBreakLine thinks that - * spaces don't occupy pixels at the end of the break, which is - * also something we like to decide for ourself. - */ - - while ((offset > (UniCharArrayOffset)urstart) && (uchars[offset-1] == ' ')) { - offset--; - } - - /* - * Fix up left-overs for the TK_WHOLE_WORDS case. - */ - - if (flags & TK_WHOLE_WORDS) { - if(flags & TK_AT_LEAST_ONE) { - - /* - * If we are the the start of the range, we need to look - * forward. If we are not at the end of a word, we must - * be in the middle of the first word, so we also look - * forward. - */ - - if ((offset == (UniCharArrayOffset)urstart) || (uchars[offset] != ' ')) { - while ((offset < (UniCharArrayOffset)urend) - && (uchars[offset] != ' ')) { - offset++; - } - } - } else { - - /* - * If we are not at the end of a word, we need to look - * backward. - */ - - if ((offset != (UniCharArrayOffset)urend) && (uchars[offset] != ' ')) { - while ((offset > (UniCharArrayOffset)urstart) - && (uchars[offset-1] != ' ')) { - offset--; - } - while ((offset > (UniCharArrayOffset)urstart) - && (uchars[offset-1] == ' ')) { - offset--; - } - } - } - } - } - - if (offset > (UniCharArrayOffset)urend) { - offset = urend; - } - - /* - * If "flags" says that we don't actually want a word break, we need - * to find the next character break ourself, as ATSUBreakLine() will - * only give us word breaks. Do a simple linear search. - */ - - if ((err != kATSULineBreakInWord) - && !(flags & TK_WHOLE_WORDS) - && (offset <= (UniCharArrayOffset)urend)) { - - UniCharArrayOffset lastOffset = offset; - UniCharArrayOffset nextoffset; - int lastX = -1; - int wantonemorechar = -1; /* undecided */ - - while (offset <= (UniCharArrayOffset)urend) { - - if (flags & TK_ISOLATE_END) { - TkMacOSXLayoutSetString(fontPtr, &drawingContext, - uchars, offset); - } - curX = MeasureStringWidth(fontPtr, urstart, offset); + /* + * ATSUBreakLine includes the whitespace that separates words, + * but we don't want that. Besides, ATSUBreakLine thinks that + * spaces don't occupy pixels at the end of the break, which is + * also something we like to decide for ourself. + */ + + while ((offset > (UniCharArrayOffset)urstart) && + (uchars[offset-1] == ' ')) { + offset--; + } + + /* + * Fix up left-overs for the TK_WHOLE_WORDS case. + */ + + if (flags & TK_WHOLE_WORDS) { + if (flags & TK_AT_LEAST_ONE) { + /* + * If we are the the start of the range, we need to look + * forward. If we are not at the end of a word, we must + * be in the middle of the first word, so we also look + * forward. + */ + + if ((offset == (UniCharArrayOffset)urstart) || + (uchars[offset] != ' ')) { + while ((offset < (UniCharArrayOffset)urend) + && (uchars[offset] != ' ')) { + offset++; + } + } + } else { + /* + * If we are not at the end of a word, we need to look + * backward. + */ + + if ((offset != (UniCharArrayOffset)urend) && + (uchars[offset] != ' ')) { + while ((offset > (UniCharArrayOffset)urstart) + && (uchars[offset-1] != ' ')) { + offset--; + } + while ((offset > (UniCharArrayOffset)urstart) + && (uchars[offset-1] == ' ')) { + offset--; + } + } + } + } + } + + if (offset > (UniCharArrayOffset)urend) { + offset = urend; + } + + /* + * If "flags" says that we don't actually want a word break, we need + * to find the next character break ourself, as ATSUBreakLine() will + * only give us word breaks. Do a simple linear search. + */ + + if ((err != kATSULineBreakInWord) + && !(flags & TK_WHOLE_WORDS) + && (offset <= (UniCharArrayOffset)urend)) { + UniCharArrayOffset lastOffset = offset; + UniCharArrayOffset nextoffset; + int lastX = -1; + int wantonemorechar = -1; /* undecided */ + + while (offset <= (UniCharArrayOffset)urend) { + if (flags & TK_ISOLATE_END) { + LayoutSetString(fontPtr, NULL, uchars, offset); + } + curX = MeasureStringWidth(fontPtr, urstart, offset); #ifdef TK_MAC_DEBUG_FONTS - fprintf(stderr, "measure: '%.*s', try until=%d, width=%d\n", - rangeLength, source+rangeStart, (int) offset, curX); + TkMacOSXDbgMsg("measure: '%.*s', try until=%ld, width=%d", + rangeLength, source+rangeStart, offset, curX); #endif - if (curX > maxLength) { - - /* - * Even if we are over the limit, we may want another - * character in some situations. Than we keep looking - * for one more character. - */ - - if (wantonemorechar == -1) { - wantonemorechar = - ((flags & TK_AT_LEAST_ONE) - && (lastOffset == (UniCharArrayOffset)urstart)) - || - ((flags & TK_PARTIAL_OK) - && (lastX != maxLength)) - ; - if (!wantonemorechar) { - break; - } - lastX = curX; - } - - /* - * There may belong combining marks to this character. - * Wait for a new curX to collect them all. - */ - - if (lastX != curX) { - break; - } - } - - /* - * Save this position, so we can come back to it. - */ - - lastX = curX; - lastOffset = offset; - - /* - * Increment offset by one character, taking combining marks - * into account. - */ - - if (offset >= (UniCharArrayOffset)urend) { - break; - } - nextoffset = 0; - if (flags & TK_ISOLATE_END) { - TkMacOSXLayoutSetString(fontPtr, &drawingContext, - uchars, ulen); - } - err = ATSUNextCursorPosition( - fontPtr->atsuLayout, - offset, - kATSUByCluster, - &nextoffset); - if (err != noErr) { -#ifdef TK_MAC_DEBUG_FONTS - fprintf(stderr, "ATSUNextCursorPosition(): " - "Error %d\n", (int) err); -#endif - break; - } - if (nextoffset <= offset) { + if (curX > maxLength) { + /* + * Even if we are over the limit, we may want another + * character in some situations. Than we keep looking + * for one more character. + */ + + if (wantonemorechar == -1) { + wantonemorechar = ((flags & TK_AT_LEAST_ONE) && + (lastOffset == (UniCharArrayOffset)urstart)) || + ((flags & TK_PARTIAL_OK) && + (lastX != maxLength)); + if (!wantonemorechar) { + break; + } + lastX = curX; + } + + /* + * There may belong combining marks to this character. + * Wait for a new curX to collect them all. + */ + + if (lastX != curX) { + break; + } + } + + /* + * Save this position, so we can come back to it. + */ + + lastX = curX; + lastOffset = offset; + + /* + * Increment offset by one character, taking combining marks + * into account. + */ + + if (offset >= (UniCharArrayOffset)urend) { + break; + } + nextoffset = 0; + if (flags & TK_ISOLATE_END) { + LayoutSetString(fontPtr, NULL, uchars, ulen); + } + err = ChkErr(ATSUNextCursorPosition, fontPtr->atsuLayout, + offset, kATSUByCluster, &nextoffset); + if (err != noErr) { + break; + } + if (nextoffset <= offset) { #ifdef TK_MAC_DEBUG_FONTS - fprintf(stderr, "ATSUNextCursorPosition(): " - "Can't move further " - "(shouldn't happen, bad data?)\n"); + TkMacOSXDbgMsg("ATSUNextCursorPosition: Can't move further" + " (shouldn't happen, bad data?)"); #endif - break; - } - - offset = nextoffset; - } - - /* - * We have overshot one character, so backup one position. - */ - - curX = lastX; - offset = lastOffset; - } - - if (curX < 0) { - if (flags & TK_ISOLATE_END) { - TkMacOSXLayoutSetString(fontPtr, &drawingContext, - uchars, offset); - } - curX = MeasureStringWidth(fontPtr, urstart, offset); - } - - curByte = Tcl_UtfAtIndex(source, offset) - source; - curByte -= rangeStart; + break; + } + + offset = nextoffset; + } + + /* + * We have overshot one character, so backup one position. + */ + + curX = lastX; + offset = lastOffset; + } + + if (curX < 0) { + if (flags & TK_ISOLATE_END) { + LayoutSetString(fontPtr, NULL, uchars, offset); + } + curX = MeasureStringWidth(fontPtr, urstart, offset); + } + + curByte = Tcl_UtfAtIndex(source, offset) - source; + curByte -= rangeStart; } Tcl_DStringFree(&ucharBuffer); -#if TK_MAC_USE_QUARZ - TkMacOSXQuarzEndDraw(&drawingContext); -#endif - #ifdef TK_MAC_DEBUG_FONTS - fflush(stdout); - fprintf(stderr, "measure: '%.*s', maxpix=%d, -> width=%d, bytes=%d, " - "flags=%s%s%s%s\n", - rangeLength, source+rangeStart, maxLength, curX, curByte, - flags & TK_PARTIAL_OK ? "partialOk " : "", - flags & TK_WHOLE_WORDS ? "wholeWords " : "", - flags & TK_AT_LEAST_ONE ? "atLeastOne " : "", - flags & TK_ISOLATE_END ? "isolateEnd " : ""); - fflush(stderr); + TkMacOSXDbgMsg("measure: '%.*s', maxpix=%d, -> width=%d, bytes=%d, " + "flags=%s%s%s%s", rangeLength, source+rangeStart, maxLength, curX, + curByte, + flags & TK_PARTIAL_OK ? "partialOk " : "", + flags & TK_WHOLE_WORDS ? "wholeWords " : "", + flags & TK_AT_LEAST_ONE ? "atLeastOne " : "", + flags & TK_ISOLATE_END ? "isolateEnd " : ""); #endif *lengthPtr = curX; @@ -999,360 +970,120 @@ TkpMeasureCharsInContext( * * Tk_DrawChars -- * - * Draw a string of characters on the screen. + * Draw a string of characters on the screen. * - * With ATSUI we need the line context to do this right, so we have the - * actual implementation in TkpDrawCharsInContext(). + * With ATSUI we need the line context to do this right, so we have the + * actual implementation in TkpDrawCharsInContext(). * * Results: - * - * None. + * None. * * Side effects: - * - * Information gets drawn on the screen. + * Information gets drawn on the screen. * *--------------------------------------------------------------------------- */ void Tk_DrawChars( - Display * display, /* Display on which to draw. */ - Drawable drawable, /* Window or pixmap in which to draw. */ - GC gc, /* Graphics context for drawing characters. */ - Tk_Font tkfont, /* Font in which characters will be drawn; must - * be the same as font used in GC. */ - const char * source, /* UTF-8 string to be displayed. Need not be - * '\0' terminated. All Tk meta-characters - * (tabs, control characters, and newlines) - * should be stripped out of the string that is - * passed to this function. If they are not - * stripped out, they will be displayed as - * regular printing characters. */ - int numBytes, /* Number of bytes in string. */ - int x, int y) /* Coordinates at which to place origin of the - * string when drawing. */ + Display *display, /* Display on which to draw. */ + Drawable drawable, /* Window or pixmap in which to draw. */ + GC gc, /* Graphics context for drawing characters. */ + Tk_Font tkfont, /* Font in which characters will be drawn; must + * be the same as font used in GC. */ + const char *source, /* UTF-8 string to be displayed. Need not be + * '\0' terminated. All Tk meta-characters + * (tabs, control characters, and newlines) + * should be stripped out of the string that + * is passed to this function. If they are not + * stripped out, they will be displayed as + * regular printing characters. */ + int numBytes, /* Number of bytes in string. */ + int x, int y) /* Coordinates at which to place origin of the + * string when drawing. */ { TkpDrawCharsInContext(display, drawable, gc, tkfont, source, numBytes, - 0, numBytes, x, y); + 0, numBytes, x, y); } - /* *--------------------------------------------------------------------------- * * TkpDrawCharsInContext -- * - * Draw a string of characters on the screen like Tk_DrawChars(), with - * access to all the characters on the line for context. + * Draw a string of characters on the screen like Tk_DrawChars(), with + * access to all the characters on the line for context. * * Results: - * None. + * None. * * Side effects: - * Information gets drawn on the screen. + * Information gets drawn on the screen. * * Todo: - * - * We could try to implement a correct stipple algorithm. - * - * The fiddling with QD GraphPorts can be replaced with just working - * with the Quarz CGContext (see TkMacOSXQuarzStartDraw()), once we - * decide to stick to Quarz and really forget about QD drawing in here. + * Stippled text drawing. * *--------------------------------------------------------------------------- */ void TkpDrawCharsInContext( - Display * display, /* Display on which to draw. */ - Drawable drawable, /* Window or pixmap in which to draw. */ - GC gc, /* Graphics context for drawing characters. */ - Tk_Font tkfont, /* Font in which characters will be drawn; must - * be the same as font used in GC. */ - const char * source, /* UTF-8 string to be displayed. Need not be - * '\0' terminated. All Tk meta-characters - * (tabs, control characters, and newlines) - * should be stripped out of the string that is - * passed to this function. If they are not - * stripped out, they will be displayed as - * regular printing characters. */ - int numBytes, /* Number of bytes in string. */ - int rangeStart, /* Index of first byte to draw. */ - int rangeLength, /* Length of range to draw in bytes. */ - int x, int y) /* Coordinates at which to place origin of the - * whole (not just the range) string when - * drawing. */ -{ - const MacFont * fontPtr; - MacDrawable * macWin; - RGBColor macColor, origColor; - GWorldPtr destPort; - CGrafPtr saveWorld; - GDHandle saveDevice; - BitMapPtr stippleMap; - Rect portRect; - - fontPtr = (const MacFont *) tkfont; - macWin = (MacDrawable *) drawable; - - destPort = TkMacOSXGetDrawablePort(drawable); - GetPortBounds(destPort, &portRect); - GetGWorld(&saveWorld, &saveDevice); - SetGWorld(destPort, NULL); - - TkMacOSXSetUpClippingRgn(drawable); - TkMacOSXSetUpGraphicsPort(gc, destPort); - - GetForeColor(&origColor); - - if ((gc->fill_style == FillStippled - || gc->fill_style == FillOpaqueStippled) - && gc->stipple != None) { - - Pixmap pixmap; - GWorldPtr bufferPort; - Pattern white; - - stippleMap = TkMacOSXMakeStippleMap(drawable, gc->stipple); - - pixmap = Tk_GetPixmap(display, drawable, - stippleMap->bounds.right, stippleMap->bounds.bottom, 0); - - bufferPort = TkMacOSXGetDrawablePort(pixmap); - SetGWorld(bufferPort, NULL); - - if (TkSetMacColor(gc->foreground, &macColor)) { - RGBForeColor(&macColor); - } - GetQDGlobalsWhite(&white); - ShowPen(); - FillRect(&stippleMap->bounds, &white); - MacFontDrawText(fontPtr, source, numBytes, rangeStart, rangeLength, - 0, 0); - HidePen(); - - SetGWorld(destPort, NULL); - - CopyDeepMask(GetPortBitMapForCopyBits(bufferPort), stippleMap, - GetPortBitMapForCopyBits(destPort), &stippleMap->bounds, - &stippleMap->bounds, &portRect, - srcOr, NULL); - - /* - * TODO: this doesn't work quite right - it does a blend. you can't - * draw white text when you have a stipple. - */ - - Tk_FreePixmap(display, pixmap); - ckfree(stippleMap->baseAddr); - ckfree((char *)stippleMap); - } else { - if (TkSetMacColor(gc->foreground, &macColor)) { - RGBForeColor(&macColor); - } - ShowPen(); - MacFontDrawText(fontPtr, source, numBytes, rangeStart, rangeLength, - macWin->xOff + x, macWin->yOff + y); - HidePen(); - } - - RGBForeColor(&origColor); - - SetGWorld(saveWorld, saveDevice); -} - -#if TK_MAC_USE_QUARZ -#define RGBFLOATRED(c) (float)((float)(c.red) / 65535.0f) -#define RGBFLOATGREEN(c) (float)((float)(c.green) / 65535.0f) -#define RGBFLOATBLUE(c) (float)((float)(c.blue) / 65535.0f) -/* - *------------------------------------------------------------------------- - * - * TkMacOSXQuarzStartDraw -- - * - * Setup a Quarz CGContext from the current QD GraphPort for use in - * drawing or measuring. - * - * Results: - * - * A CGContext is allocated, configured and returned in - * drawingContextPtr. Also drawingContextPtr->portRect is filled in. - * - * Side effects: - * - * None. - * - * Assumptions: - * - * The current QD GraphPort contains all the data necessary. This is - * clearly the case for the actual drawing, but not so clear for - * measuring. OTOH for measuring the specific parameters are not really - * interesting and the GraphPort is not changed either. The - * availability of a CGContext may be important for the measuring - * process though. - * - *------------------------------------------------------------------------- - */ - -void -TkMacOSXQuarzStartDraw( - DrawingContext * drawingContextPtr) /* Quarz context data filled in - * by this function. */ -{ - GDHandle currentDevice; - CGrafPtr destPort; - RGBColor macColor; - CGContextRef outContext; - OSStatus err; - Rect boundsRect; - static RgnHandle clipRgn = NULL; - - GetGWorld(&destPort, ¤tDevice); - - err = QDBeginCGContext(destPort, &outContext); - - if (err == noErr && outContext) { - /* - * Now clip the CG Context to the port. We also have to intersect our clip - * region with the port visible region so we don't overwrite the window - * decoration. - */ - - if (!clipRgn) { - clipRgn = NewRgn(); - } - - GetPortBounds(destPort, &boundsRect); - - RectRgn(clipRgn, &boundsRect); - SectRegionWithPortClipRegion(destPort, clipRgn); - SectRegionWithPortVisibleRegion(destPort, clipRgn); - ClipCGContextToRegion(outContext, &boundsRect, clipRgn); - SetEmptyRgn(clipRgn); - - /* - * Note: You have to call SyncCGContextOriginWithPort - * AFTER all the clip region manipulations. - */ - - SyncCGContextOriginWithPort(outContext, destPort); - - /* - * Scale the color values, as QD uses UInt16 with the range [0..2^16-1] - * while Quarz uses float with [0..1]. NB: Only - * CGContextSetRGBFillColor() seems to be actually used by ATSU. - */ - - GetForeColor(&macColor); - CGContextSetRGBFillColor(outContext, - RGBFLOATRED(macColor), - RGBFLOATGREEN(macColor), - RGBFLOATBLUE(macColor), - 1.0f); - #ifdef TK_MAC_DEBUG_FONTS - } else { - fprintf(stderr, "QDBeginCGContext(): Error %d\n", (int) err); - #endif - } - - drawingContextPtr->graphPort = destPort; - drawingContextPtr->cgContext = outContext; - drawingContextPtr->portRect = boundsRect; - -} - -/* - *------------------------------------------------------------------------- - * - * TkMacOSXQuarzEndDraw -- - * - * Free the Quarz CGContext in drawingContextPtr. - * - * Results: - * - * The CGContext is de-allocated. drawingContextPtr->cgContext will be - * invalid after this. - * - * Side effects: - * - * None. - * - *------------------------------------------------------------------------- - */ - -void -TkMacOSXQuarzEndDraw( - DrawingContext * drawingContextPtr) -{ - if (drawingContextPtr->cgContext) { - QDEndCGContext( - drawingContextPtr->graphPort, - &drawingContextPtr->cgContext); - } -} -#endif /* TK_MAC_USE_QUARZ */ - -/* - *------------------------------------------------------------------------- - * - * MacFontDrawText -- - * - * Helper function for Tk_DrawChars. Draws characters, using the - * screen font in fontPtr to draw multilingual characters. - * - * Results: - * None. - * - * Side effects: - * Information gets drawn on the screen. - * - *------------------------------------------------------------------------- - */ - -static void -MacFontDrawText( - const MacFont * fontPtr, /* Contains font to use when drawing - * following string. */ - const char * source, /* Potentially multilingual UTF-8 string. */ - int numBytes, /* Length of string in bytes. */ - int rangeStart, /* Index of first byte to draw. */ - int rangeLength, /* Length of range to draw in bytes. */ - int x, int y) /* Coordinates at which to place origin of - * string when drawing. */ + Display *display, /* Display on which to draw. */ + Drawable drawable, /* Window or pixmap in which to draw. */ + GC gc, /* Graphics context for drawing characters. */ + Tk_Font tkfont, /* Font in which characters will be drawn; must + * be the same as font used in GC. */ + const char * source, /* UTF-8 string to be displayed. Need not be + * '\0' terminated. All Tk meta-characters + * (tabs, control characters, and newlines) + * should be stripped out of the string that + * is passed to this function. If they are not + * stripped out, they will be displayed as + * regular printing characters. */ + int numBytes, /* Number of bytes in string. */ + int rangeStart, /* Index of first byte to draw. */ + int rangeLength, /* Length of range to draw in bytes. */ + int x, int y) /* Coordinates at which to place origin of the + * whole (not just the range) string when + * drawing. */ { + const MacFont * fontPtr = (const MacFont *) tkfont; + MacDrawable *macWin = (MacDrawable *) drawable; Fixed fx, fy; int ulen, urstart, urlen; const UniChar * uchars; int lineOffset; - DrawingContext drawingContext; - OSStatus err; - + TkMacOSXDrawingContext drawingContext; #if !TK_MAC_COALESCE_LINE Tcl_DString runString; #endif + TkMacOSXSetupDrawingContext(drawable, gc, 1, &drawingContext); -#if TK_MAC_USE_QUARZ - TkMacOSXQuarzStartDraw(&drawingContext); - - /* - * Turn the y coordinate upside-down for Quarz drawing. We would have - * liked to just use a CTM transform in the CGContext, but than we get - * upside-down text, so doing it that way gets more painfull than to just - * hack around the problem right here. - */ - - y = drawingContext.portRect.bottom - drawingContext.portRect.top - y; - fy = IntToFixed(y); -#else - fy = IntToFixed(y); +#if 0 + /* TODO: implement stippled text drawing */ + if ((gc->fill_style == FillStippled + || gc->fill_style == FillOpaqueStippled) + && gc->stipple != None) { + #error Stippling not implemented + } #endif + x += macWin->xOff; + y += macWin->yOff; + /* Turn the y coordinate upside-down for Quarz drawing. */ + if (drawingContext.context) { + CGContextConcatCTM(drawingContext.context, CGAffineTransformMake(1.0, + 0.0, 0.0, -1.0, 0.0, drawingContext.portBounds.bottom - + drawingContext.portBounds.top)); + y = drawingContext.portBounds.bottom - + drawingContext.portBounds.top - y; + } + fy = IntToFixed(y); #if TK_MAC_COALESCE_LINE UpdateLineBuffer( - fontPtr, &drawingContext, source, numBytes, x, y, &lineOffset); + fontPtr, &drawingContext, source, numBytes, x, y, &lineOffset); fx = IntToFixed(currentLeft); @@ -1366,67 +1097,54 @@ MacFontDrawText( uchars = Tcl_UtfToUniCharDString(source, numBytes, &runString); ulen = Tcl_DStringLength(&runString) / sizeof(uchars[0]); - TkMacOSXLayoutSetString(fontPtr, &drawingContext, uchars, ulen); + LayoutSetString(fontPtr, &drawingContext, uchars, ulen); #endif urstart = Tcl_NumUtfChars(source, rangeStart); urlen = Tcl_NumUtfChars(source+rangeStart,rangeLength); - err = ATSUDrawText( - fontPtr->atsuLayout, - lineOffset+urstart, urlen, - fx, fy); -#ifdef TK_MAC_DEBUG_FONTS - if (err != noErr) { - fprintf(stderr, "ATSUDrawText(): Error %d\n", (int) err); - } -#endif + ChkErr(ATSUDrawText, fontPtr->atsuLayout, lineOffset+urstart, urlen, fx, + fy); #if !TK_MAC_COALESCE_LINE Tcl_DStringFree(&runString); #endif -#if TK_MAC_USE_QUARZ - TkMacOSXQuarzEndDraw(&drawingContext); -#endif + TkMacOSXRestoreDrawingContext(&drawingContext); } - /* *--------------------------------------------------------------------------- * * MeasureStringWidth -- * - * Low-level measuring of strings. + * Low-level measuring of strings. * * Results: - * - * The width of the string in pixels. + * The width of the string in pixels. * * Side effects: - * - * None. + * None. * * Assumptions: - * - * fontPtr->atsuLayout is setup with the actual string data to measure. + * fontPtr->atsuLayout is setup with the actual string data to measure. * *--------------------------------------------------------------------------- */ static int MeasureStringWidth( - const MacFont * fontPtr, /* Contains font, ATSU layout and string data - * to measure. */ - int start, int end) /* Start and end positions to measure in that - * string. */ + const MacFont *fontPtr, /* Contains font, ATSU layout and string data + * to measure. */ + int start, int end) /* Start and end positions to measure in that + * string. */ { /* * This implementation of measuring via ATSUGetGlyphBounds() does not * quite conform with the specification given for [font measure]: * - * The return value is the total width in pixels of text, not - * including the extra pixels used by highly exagerrated characters - * such as cursive "f". + * The return value is the total width in pixels of text, not + * including the extra pixels used by highly exagerrated characters + * such as cursive "f". * * Instead the result of ATSUGetGlyphBounds() *does* include these * "extra pixels". @@ -1434,26 +1152,18 @@ MeasureStringWidth( ATSTrapezoid bounds; ItemCount numBounds; - OSStatus err; if (end <= start) { - return 0; + return 0; } bounds.upperRight.x = bounds.upperLeft.x = 0; - err = ATSUGetGlyphBounds( - fontPtr->atsuLayout, - 0, 0, - start, end-start, - kATSUseFractionalOrigins, - 1, &bounds, &numBounds); + ChkErr(ATSUGetGlyphBounds, fontPtr->atsuLayout, 0, 0, start, end-start, + kATSUseFractionalOrigins, 1, &bounds, &numBounds); #ifdef TK_MAC_DEBUG_FONTS - if (err != noErr) { - fprintf(stderr, "ATSUGetGlyphBounds(): Error %d\n", (int) err); - } else if (numBounds < 1) { - fprintf(stderr, "ATSUGetGlyphBounds(): No output\n"); - } else if (numBounds > 1) { - fprintf(stderr, "ATSUGetGlyphBounds(): More output\n"); + if (numBounds < 1 || numBounds > 1) { + TkMacOSXDbgMsg("ATSUGetGlyphBounds: %s output", + numBounds < 1 ? "No " : "More"); } #endif @@ -1466,58 +1176,57 @@ MeasureStringWidth( * * UpdateLineBuffer -- * - * See the general dicussion of TK_MAC_COALESCE_LINE on the header - * pages. This function maintains the data for this feature. + * See the general dicussion of TK_MAC_COALESCE_LINE on the header + * pages. This function maintains the data for this feature. * * Results: * - * The Tcl_UniChar string of the whole line as seen so far. + * The Tcl_UniChar string of the whole line as seen so far. * * Side effects: + * "*offset" is filled with the index of the first new character in + * "currentLine". The globals currentLine, currentY, currentLeft, + * currentRight and currentFontPtr are updated as necessary. * - * "*offset" is filled with the index of the first new character in - * "currentLine". The globals currentLine, currentY, currentLeft, - * currentRight and currentFontPtr are updated as necessary. - * - * The currentLine string is set as the current text in - * fontPtr->atsuLayout (see TkMacOSXLayoutSetString()). + * The currentLine string is set as the current text in + * fontPtr->atsuLayout (see LayoutSetString()). * *------------------------------------------------------------------------- */ static const Tcl_UniChar * UpdateLineBuffer( - const MacFont * fontPtr,/* The font to be used for the new piece of - * text. */ - const DrawingContext * drawingContextPtr, - /* The Quarz drawing parameters. Needed for - * measuring the new piece. */ - const char * source, /* A new piece of line to be added. */ - int numBytes, /* Length of the new piece. */ - int x, int y, /* Position of the new piece in the window. */ - int * offset) /* Filled with the offset of the new piece in - * currentLine. */ + const MacFont *fontPtr, /* The font to be used for the new piece of + * text. */ + const TkMacOSXDrawingContext *drawingContextPtr, + /* The Quarz drawing parameters. Needed for + * measuring the new piece. */ + const char *source, /* A new piece of line to be added. */ + int numBytes, /* Length of the new piece. */ + int x, int y, /* Position of the new piece in the window. */ + int *offset) /* Filled with the offset of the new piece in + * currentLine. */ { const Tcl_UniChar * uchars; int ulen; if (y != currentY - || x < currentRight-1 || x > currentRight+2 - || currentFontPtr != fontPtr) { - Tcl_DStringFree(¤tLine); - Tcl_DStringInit(¤tLine); - currentY = y; - currentLeft = x; - currentFontPtr = fontPtr; - *offset = 0; + || x < currentRight-1 || x > currentRight+2 + || currentFontPtr != fontPtr) { + Tcl_DStringFree(¤tLine); + Tcl_DStringInit(¤tLine); + currentY = y; + currentLeft = x; + currentFontPtr = fontPtr; + *offset = 0; } else { - *offset = Tcl_DStringLength(¤tLine) / 2; + *offset = Tcl_DStringLength(¤tLine) / 2; } Tcl_UtfToUniCharDString(source, numBytes, ¤tLine); uchars = (const Tcl_UniChar*) Tcl_DStringValue(¤tLine); ulen = Tcl_DStringLength(¤tLine) / sizeof(*uchars); - TkMacOSXLayoutSetString(fontPtr, drawingContextPtr, uchars, ulen); + LayoutSetString(fontPtr, drawingContextPtr, uchars, ulen); currentRight = x + MeasureStringWidth(fontPtr, *offset, ulen); return uchars; @@ -1529,33 +1238,33 @@ UpdateLineBuffer( * * InitFont -- * - * Helper for TkpGetNativeFont() and TkpGetFontFromAttributes(). - * Initializes the memory for a MacFont that wraps the - * platform-specific data. + * Helper for TkpGetNativeFont() and TkpGetFontFromAttributes(). + * Initializes the memory for a MacFont that wraps the + * platform-specific data. * - * The caller is responsible for initializing the fields of the TkFont - * that are used exclusively by the generic TkFont code, and for - * releasing those fields before calling TkpDeleteFont(). + * The caller is responsible for initializing the fields of the TkFont + * that are used exclusively by the generic TkFont code, and for + * releasing those fields before calling TkpDeleteFont(). * * Results: - * Fills the MacFont structure. + * Fills the MacFont structure. * * Side effects: - * Memory allocated. + * Memory allocated. * *--------------------------------------------------------------------------- */ static void InitFont( - Tk_Window tkwin, /* For display where font will be used. */ - FMFontFamily familyId, /* The font family to initialize for. */ - const char * familyName,/* The font family name, if known. Otherwise - * this can be NULL. */ - int size, /* Point size for the font. */ - int qdStyle, /* QuickDraw style bits. */ - MacFont * fontPtr) /* Filled with information constructed from the - * above arguments. */ + Tk_Window tkwin, /* For display where font will be used. */ + FMFontFamily familyId, /* The font family to initialize for. */ + const char * familyName, /* The font family name, if known. Otherwise + * this can be NULL. */ + int size, /* Point size for the font. */ + int qdStyle, /* QuickDraw style bits. */ + MacFont * fontPtr) /* Filled with information constructed from the + * above arguments. */ { OSStatus err; FontInfo fi; @@ -1565,38 +1274,30 @@ InitFont( int periodWidth, wWidth; if (size == 0) { - size = GetDefFontSize(); + size = GetDefFontSize(); } points = (short) TkFontGetPoints(tkwin, size); - - err = FetchFontInfo(familyId, points, qdStyle, &fi); -#ifdef TK_MAC_DEBUG_FONTS - if (err != noErr) { - fprintf(stderr, "FetchFontInfo(): Error %d\n", (int) err); - } -#endif - + ChkErr(FetchFontInfo, familyId, points, qdStyle, &fi); if (familyName == NULL) { - char name[256] = ""; - const MacFontFamily * familyPtr; - - err = GetFontFamilyName(familyId, name, sizeof(name)); - if (err == noErr) { - - /* - * We find the canonical font name, so we can avoid unnecessary - * memory management. - */ - - familyPtr = FindFontFamily(name); - if (familyPtr != NULL) { - familyName = familyPtr->name; - } else { + char name[256] = ""; + const MacFontFamily * familyPtr; + + err = ChkErr(GetFontFamilyName, familyId, name, sizeof(name)); + if (err == noErr) { + /* + * We find the canonical font name, so we can avoid unnecessary + * memory management. + */ + + familyPtr = FindFontFamily(name); + if (familyPtr != NULL) { + familyName = familyPtr->name; + } else { #ifdef TK_MAC_DEBUG_FONTS - fprintf(stderr, "Font family '%s': Not found\n", name); + TkMacOSXDbgMsg("Font family '%s' not found", name); #endif - } - } + } + } } fontPtr->font.fid = (Font) fontPtr; @@ -1613,8 +1314,8 @@ InitFont( /* * Note: Macs measure the line height as ascent + descent + - * leading. Leading as a separate entity does not exist in X11 - * and Tk. We add it to the ascent at the moment, because adding + * leading. Leading as a separate entity does not exist in X11 + * and Tk. We add it to the ascent at the moment, because adding * it to the descent, as the Mac docs would indicate, would change * the position of self-drawn underlines. */ @@ -1627,9 +1328,8 @@ InitFont( fontPtr->qdSize = points; fontPtr->qdStyle = (short) qdStyle; - InitATSUObjects( - familyId, points, qdStyle, - &fontPtr->atsuFontId, &fontPtr->atsuLayout, &fontPtr->atsuStyle); + InitATSUObjects(familyId, points, qdStyle, &fontPtr->atsuFontId, + &fontPtr->atsuLayout, &fontPtr->atsuStyle); Tk_MeasureChars((Tk_Font)fontPtr, ".", 1, -1, 0, &periodWidth); Tk_MeasureChars((Tk_Font)fontPtr, "W", 1, -1, 0, &wWidth); @@ -1645,31 +1345,29 @@ InitFont( * * InitATSUObjects -- * - * Helper for InitFont(). Initializes the ATSU data handles for a - * MacFont. + * Helper for InitFont(). Initializes the ATSU data handles for a + * MacFont. * * Results: - * - * Sets up all we know and can do at this point in time in fontIdPtr, - * layoutPtr and stylePtr. + * Sets up all we know and can do at this point in time in fontIdPtr, + * layoutPtr and stylePtr. * * Side effects: - * - * Allocates data structures inside of ATSU. + * Allocates data structures inside of ATSU. * *--------------------------------------------------------------------------- */ static void InitATSUObjects( - FMFontFamily familyId, /* The font family to use. */ - short ptSize, short qdStyles, /* The additional font parameters. */ - ATSUFontID * fontIdPtr, /* Filled with the font id. */ - ATSUTextLayout * layoutPtr, /* Filled with the ATSU layout handle. */ - ATSUStyle * stylePtr) /* Filled with the ATSU style handle, - * configured with all parameters. */ + FMFontFamily familyId, /* The font family to use. */ + short ptSize, short qdStyles, + /* The additional font parameters. */ + ATSUFontID *fontIdPtr, /* Filled with the font id. */ + ATSUTextLayout *layoutPtr, /* Filled with the ATSU layout handle. */ + ATSUStyle *stylePtr) /* Filled with the ATSU style handle, + * configured with all parameters. */ { - OSStatus err; FMFontStyle stylesDone, stylesLeft; /* @@ -1684,14 +1382,8 @@ InitATSUObjects( * Generate a font id from family id and QD style bits. */ - err = FMGetFontFromFontFamilyInstance( - familyId, qdStyles, fontIdPtr, &stylesDone); -#ifdef TK_MAC_DEBUG_FONTS - if (err != noErr) { - fprintf(stderr, "FMGetFontFromFontFamilyInstance(): Error %d\n", - (int) err); - } -#endif + ChkErr(FMGetFontFromFontFamilyInstance, familyId, qdStyles, fontIdPtr, + &stylesDone); /* * We see what style bits are left and tell ATSU to synthesize what's @@ -1704,25 +1396,15 @@ InitATSUObjects( * Create the style and set its attributes. */ - err = ATSUCreateStyle(stylePtr); -#ifdef TK_MAC_DEBUG_FONTS - if (err != noErr) { - fprintf(stderr, "ATSUCreateStyle(): Error %d\n", (int) err); - } -#endif + ChkErr(ATSUCreateStyle, stylePtr); InitATSUStyle(*fontIdPtr, ptSize, stylesLeft, *stylePtr); /* - * Create the layout. Note: We can't set the layout attributes here, + * Create the layout. Note: We can't set the layout attributes here, * because the text and the style must be set first. */ - err = ATSUCreateTextLayout(layoutPtr); -#ifdef TK_MAC_DEBUG_FONTS - if (err != noErr) { - fprintf(stderr, "ATSUCreateTextLayout(): Error %d\n", (int) err); - } -#endif + ChkErr(ATSUCreateTextLayout, layoutPtr); /*InitATSULayout(*layoutPtr);*/ } @@ -1731,25 +1413,24 @@ InitATSUObjects( * * InitATSUStyle -- * - * Helper for InitATSUObjects(). Initializes the ATSU style for a - * MacFont. + * Helper for InitATSUObjects(). Initializes the ATSU style for a + * MacFont. * * Results: - * - * Sets up all parameters needed for an ATSU style. + * Sets up all parameters needed for an ATSU style. * * Side effects: - * - * Allocates data structures for the style inside of ATSU. + * Allocates data structures for the style inside of ATSU. * *--------------------------------------------------------------------------- */ static void InitATSUStyle( - ATSUFontID fontId, /* The font id to use. */ - short ptSize, short qdStyles, /* Additional font parameters. */ - ATSUStyle style) /* The style handle to configure. */ + ATSUFontID fontId, /* The font id to use. */ + short ptSize, short qdStyles, + /* Additional font parameters. */ + ATSUStyle style) /* The style handle to configure. */ { /* * Attributes for the style. @@ -1757,69 +1438,57 @@ InitATSUStyle( Fixed fsize = IntToFixed(ptSize); Boolean - isBold = (qdStyles&bold) != 0, - isUnderline = (qdStyles&underline) != 0, - isItalic = (qdStyles&italic) != 0; + isBold = (qdStyles&bold) != 0, + isUnderline = (qdStyles&underline) != 0, + isItalic = (qdStyles&italic) != 0; ATSStyleRenderingOptions options = - antialiasedTextEnabled == -1 ? kATSStyleNoOptions : - antialiasedTextEnabled == 0 ? kATSStyleNoAntiAliasing : - kATSStyleApplyAntiAliasing; + antialiasedTextEnabled == -1 ? kATSStyleNoOptions : + antialiasedTextEnabled == 0 ? kATSStyleNoAntiAliasing : + kATSStyleApplyAntiAliasing; static const ATSUAttributeTag styleTags[] = { - kATSUFontTag, kATSUSizeTag, - kATSUQDBoldfaceTag, kATSUQDItalicTag, kATSUQDUnderlineTag, - kATSUStyleRenderingOptionsTag, + kATSUFontTag, kATSUSizeTag, + kATSUQDBoldfaceTag, kATSUQDItalicTag, kATSUQDUnderlineTag, + kATSUStyleRenderingOptionsTag, }; static const ByteCount styleSizes[] = { - sizeof(ATSUFontID), sizeof(Fixed), - sizeof(Boolean), sizeof(Boolean), sizeof(Boolean), - sizeof(ATSStyleRenderingOptions), + sizeof(ATSUFontID), sizeof(Fixed), + sizeof(Boolean), sizeof(Boolean), sizeof(Boolean), + sizeof(ATSStyleRenderingOptions), }; const ATSUAttributeValuePtr styleValues[] = { - &fontId, &fsize, - &isBold, &isItalic, &isUnderline, - &options, + &fontId, &fsize, + &isBold, &isItalic, &isUnderline, + &options, }; - OSStatus err; - - err = ATSUSetAttributes( - style, - sizeof(styleTags)/sizeof(styleTags[0]), - styleTags, styleSizes, styleValues); -#ifdef TK_MAC_DEBUG_FONTS - if (err != noErr) { - fprintf(stderr, "ATSUSetAttributes(): Error %d\n", (int) err); - } -#endif + ChkErr(ATSUSetAttributes, style, sizeof(styleTags)/sizeof(styleTags[0]), + styleTags, styleSizes, styleValues); } - /* *--------------------------------------------------------------------------- * * SetFontFeatures -- * - * Helper for InitFont(). Request specific font features of the ATSU - * style object for a MacFont. + * Helper for InitFont(). Request specific font features of the ATSU + * style object for a MacFont. * * Results: - * - * None. + * None. * * Side effects: - * - * Specific font features are enabled on the ATSU style object. + * Specific font features are enabled on the ATSU style object. * *--------------------------------------------------------------------------- */ static void SetFontFeatures( - ATSUFontID fontId, /* The font id to use. */ - int fixed, /* Is this a fixed font? */ - ATSUStyle style) /* The style handle to configure. */ + ATSUFontID fontId, /* The font id to use. */ + int fixed, /* Is this a fixed font? */ + ATSUStyle style) /* The style handle to configure. */ { /* * Don't use the standard latin ligatures, if this is determined to be a @@ -1827,24 +1496,16 @@ SetFontFeatures( */ static const ATSUFontFeatureType fixed_featureTypes[] = { - kLigaturesType, kLigaturesType + kLigaturesType, kLigaturesType }; static const ATSUFontFeatureSelector fixed_featureSelectors[] = { - kCommonLigaturesOffSelector, kRareLigaturesOffSelector + kCommonLigaturesOffSelector, kRareLigaturesOffSelector }; - OSStatus err; - if (fixed) { - err = ATSUSetFontFeatures( - style, - sizeof(fixed_featureTypes)/sizeof(fixed_featureTypes[0]), - fixed_featureTypes, fixed_featureSelectors); -#ifdef TK_MAC_DEBUG_FONTS - if (err != noErr) { - fprintf(stderr, "ATSUSetFontFeatures(): Error %d\n", (int) err); - } -#endif + ChkErr(ATSUSetFontFeatures, style, sizeof(fixed_featureTypes) / + sizeof(fixed_featureTypes[0]), fixed_featureTypes, + fixed_featureSelectors); } } @@ -1853,17 +1514,15 @@ SetFontFeatures( * * AdjustFontHeight -- * - * Helper for InitFont(). Check font height against some real world - * examples. + * Helper for InitFont(). Check font height against some real world + * examples. * * Results: - * - * None. + * None. * * Side effects: - * - * The metrics in fontPtr->font.fm are adjusted so that typical combined - * characters fit into ascent+descent. + * The metrics in fontPtr->font.fm are adjusted so that typical combined + * characters fit into ascent+descent. * *--------------------------------------------------------------------------- */ @@ -1875,7 +1534,7 @@ AdjustFontHeight( /* * The standard values for ascent, descent and leading as determined in * InitFont do not take composition into account, they are designed for - * plain ASCII characters. This code measures the actual size of some + * plain ASCII characters. This code measures the actual size of some * typical composed characters from the Latin-1 range and corrects these * factors, especially the ascent. * @@ -1883,237 +1542,174 @@ AdjustFontHeight( * than requested. * * An alternative would be to instruct ATSU to shrink oversized combined - * characters. I think I have seen that feature somewhere, but I can't + * characters. I think I have seen that feature somewhere, but I can't * find it now [BR]. */ static const UniChar chars[] - /* Auml, Aacute, Acirc, Atilde, Ccedilla */ - = {0x00C4, 0x00C1, 0x00C2, 0x00C3, 0x00C7}; + /* Auml, Aacute, Acirc, Atilde, Ccedilla */ + = {0x00C4, 0x00C1, 0x00C2, 0x00C3, 0x00C7}; static const int charslen = sizeof(chars) / sizeof(chars[0]); - - DrawingContext drawingContext; Rect size; OSStatus err; - -#if TK_MAC_USE_QUARZ - TkMacOSXQuarzStartDraw(&drawingContext); -#endif - - TkMacOSXLayoutSetString(fontPtr, &drawingContext, chars, charslen); + LayoutSetString(fontPtr, NULL, chars, charslen); size.top = size.bottom = 0; - err = ATSUMeasureTextImage( - fontPtr->atsuLayout, - 0, charslen, - 0, 0, - &size); - -#if TK_MAC_USE_QUARZ - TkMacOSXQuarzEndDraw(&drawingContext); -#endif + err = ChkErr(ATSUMeasureTextImage, fontPtr->atsuLayout, 0, charslen, 0, 0, + &size); - if (err != noErr) { -#ifdef TK_MAC_DEBUG_FONTS - fprintf(stderr, "ATSUMeasureTextImage(): Error %d\n", (int) err); -#endif - } else { - TkFontMetrics * fmPtr = &fontPtr->font.fm; - int ascent = -size.top; - int descent = size.bottom; - - if (ascent > fmPtr->ascent) { - fmPtr->ascent = ascent; - } - if (descent > fmPtr->descent) { - fmPtr->descent = descent; - } + if (err == noErr) { + TkFontMetrics * fmPtr = &fontPtr->font.fm; + int ascent = -size.top; + int descent = size.bottom; + + if (ascent > fmPtr->ascent) { + fmPtr->ascent = ascent; + } + if (descent > fmPtr->descent) { + fmPtr->descent = descent; + } } } - /* *--------------------------------------------------------------------------- * * InitATSULayout -- * - * Helper for TkMacOSXLayoutSetString(). Initializes the ATSU layout - * object for a MacFont and a specific string. + * Helper for LayoutSetString(). Initializes the ATSU layout + * object for a MacFont and a specific string. * * Results: - * - * Sets up all parameters needed for an ATSU layout object. + * Sets up all parameters needed for an ATSU layout object. * * Side effects: - * - * Allocates data structures for the layout object inside of ATSU. + * Allocates data structures for the layout object inside of ATSU. * * Assumptions: - * - * The actual string data and style information is already set by - * ATSUSetTextPointerLocation() and ATSUSetRunStyle() (see - * TkMacOSXLayoutSetString()). + * The actual string data and style information is already set by + * ATSUSetTextPointerLocation() and ATSUSetRunStyle() (see + * LayoutSetString()). * *--------------------------------------------------------------------------- */ static void InitATSULayout( - const DrawingContext * drawingContextPtr, - /* Specifies the CGContext to use. */ - ATSUTextLayout layout, /* The layout object to configure. */ - int fixed) /* Is this a fixed font? */ + const TkMacOSXDrawingContext *drawingContextPtr, + /* Specifies the CGContext to use. */ + ATSUTextLayout layout, /* The layout object to configure. */ + int fixed) /* Is this a fixed font? */ { /* * Attributes for the layout. */ - ATSLineLayoutOptions layoutOptions = - 0 + ATSLineLayoutOptions layoutOptions = 0 #if TK_MAC_COALESCE_LINE - /* - * Options to use unconditionally, when we try to do coalescing in here. - */ - | kATSLineDisableAllLayoutOperations - | kATSLineFractDisable - | kATSLineUseDeviceMetrics + /* + * Options to use unconditionally when we try to do coalescing. + */ + | kATSLineDisableAllLayoutOperations + | kATSLineFractDisable + | kATSLineUseDeviceMetrics #endif - ; + ; + CGContextRef context = drawingContextPtr ? + drawingContextPtr->context : NULL; static const ATSUAttributeTag layoutTags[] = { -#if TK_MAC_USE_QUARZ - kATSUCGContextTag, -#endif - kATSULineLayoutOptionsTag, + kATSUCGContextTag, + kATSULineLayoutOptionsTag, }; static const ByteCount layoutSizes[] = { -#if TK_MAC_USE_QUARZ - sizeof(CGContextRef), -#endif - sizeof(ATSLineLayoutOptions), + sizeof(CGContextRef), + sizeof(ATSLineLayoutOptions), }; const ATSUAttributeValuePtr layoutValues[] = { -#if TK_MAC_USE_QUARZ - (void*)&drawingContextPtr->cgContext, -#endif - &layoutOptions, + &context, + &layoutOptions, }; - OSStatus err; - /* * Ensure W(abcdefg) == W(a)*7 for fixed fonts (Latin scripts only). */ if (fixed) { - layoutOptions |= - kATSLineFractDisable - | kATSLineUseDeviceMetrics - ; - } - - err = ATSUSetLayoutControls( - layout, - sizeof(layoutTags)/sizeof(layoutTags[0]), - layoutTags, layoutSizes, layoutValues); -#ifdef TK_MAC_DEBUG_FONTS - if (err != noErr) { - fprintf(stderr, "ATSUSetLayoutControls(): Error %d\n", (int) err); + layoutOptions |= kATSLineFractDisable | kATSLineUseDeviceMetrics; } -#endif - err = ATSUSetTransientFontMatching(layout, true); -#ifdef TK_MAC_DEBUG_FONTS - if (err != noErr) { - fprintf(stderr, "ATSUSetTransientFontMatching(): Error %d\n", - (int) err); - } -#endif + ChkErr(ATSUSetLayoutControls, layout, sizeof(layoutTags) / + sizeof(layoutTags[0]), layoutTags, layoutSizes, layoutValues); + ChkErr(ATSUSetTransientFontMatching, layout, true); } /* *--------------------------------------------------------------------------- * - * TkMacOSXLayoutSetString -- + * LayoutSetString -- * - * Setup the MacFont for a specific string. + * Setup the MacFont for a specific string. * * Results: - * - * Sets up all parameters so that ATSU can work with the objects in - * MacFont. + * Sets up all parameters so that ATSU can work with the objects in + * MacFont. * * Side effects: - * - * Sets parameters on the layout object fontPtr->atsuLayout. + * Sets parameters on the layout object fontPtr->atsuLayout. * *--------------------------------------------------------------------------- */ void -TkMacOSXLayoutSetString( - const MacFont * fontPtr, /* The fontPtr to configure. */ - const DrawingContext * drawingContextPtr, - /* For the CGContext to be used.*/ - const UniChar * uchars, int ulen) /* The UniChar string to set into - * fontPtr->atsuLayout. */ +LayoutSetString( + const MacFont *fontPtr, /* The fontPtr to configure. */ + const TkMacOSXDrawingContext *drawingContextPtr, + /* For the CGContext to be used.*/ + const UniChar *uchars, int ulen) + /* The UniChar string to set into + * fontPtr->atsuLayout. */ { - OSStatus err; - err = ATSUSetTextPointerLocation( - fontPtr->atsuLayout, - uchars, kATSUFromTextBeginning, ulen, - ulen); -#ifdef TK_MAC_DEBUG_FONTS - if (err != noErr) { - fprintf(stderr, "ATSUSetTextPointerLocation(): Error %d\n", (int) err); - } -#endif + ChkErr(ATSUSetTextPointerLocation, fontPtr->atsuLayout, uchars, + kATSUFromTextBeginning, ulen, ulen); /* * Styles can only be set after the text is set. */ - err = ATSUSetRunStyle( - fontPtr->atsuLayout, fontPtr->atsuStyle, - kATSUFromTextBeginning, kATSUToTextEnd); -#ifdef TK_MAC_DEBUG_FONTS - if (err != noErr) { - fprintf(stderr, "ATSUSetRunStyle(): Error %d\n", (int) err); - } -#endif + ChkErr(ATSUSetRunStyle, fontPtr->atsuLayout, fontPtr->atsuStyle, + kATSUFromTextBeginning, kATSUToTextEnd); /* * Layout attributes can only be set after the styles are set. */ - InitATSULayout( - drawingContextPtr, fontPtr->atsuLayout, - fontPtr->font.fm.fixed); + InitATSULayout(drawingContextPtr, fontPtr->atsuLayout, + fontPtr->font.fm.fixed); } - /* *------------------------------------------------------------------------- * * ReleaseFont -- * - * Called to release the Macintosh-specific contents of a TkFont. The - * caller is responsible for freeing the memory used by the font - * itself. + * Called to release the Macintosh-specific contents of a TkFont. The + * caller is responsible for freeing the memory used by the font + * itself. * * Results: - * None. + * None. * * Side effects: - * Memory is freed. + * Memory is freed. * *--------------------------------------------------------------------------- */ static void ReleaseFont( - MacFont * fontPtr) /* The font to delete. */ + MacFont *fontPtr) /* The font to delete. */ { ATSUDisposeTextLayout(fontPtr->atsuLayout); ATSUDisposeStyle(fontPtr->atsuStyle); @@ -2124,40 +1720,40 @@ ReleaseFont( * * FindFontFamilyOrAlias, FindFontFamilyOrAliasOrFallback -- * - * Determine if any physical screen font exists on the system with The - * given family name. If the family exists, then it should be possible - * to construct some physical screen font with that family name. + * Determine if any physical screen font exists on the system with the + * given family name. If the family exists, then it should be possible + * to construct some physical screen font with that family name. * - * FindFontFamilyOrAlias also considers font aliases as determined by - * TkFontGetAliasList(). + * FindFontFamilyOrAlias also considers font aliases as determined by + * TkFontGetAliasList(). * - * FindFontFamilyOrAliasOrFallback also considers font aliases as - * determined by TkFontGetFallbacks(). + * FindFontFamilyOrAliasOrFallback also considers font aliases as + * determined by TkFontGetFallbacks(). * - * The overall algorithm to get the closest font to the one requested is - * this: + * The overall algorithm to get the closest font to the one requested is + * this: * - * try fontname - * try all aliases for fontname - * foreach fallback for fontname - * try the fallback - * try all aliases for the fallback + * try fontname + * try all aliases for fontname + * foreach fallback for fontname + * try the fallback + * try all aliases for the fallback * * Results: * - * The return value is NULL if the specified font family does not exist, - * a valid MacFontFamily* otherwise. + * The return value is NULL if the specified font family does not exist, + * a valid MacFontFamily* otherwise. * * Side effects: * - * None. + * None. * *------------------------------------------------------------------------- */ static const MacFontFamily * FindFontFamilyOrAlias( - const char * name) /* Name or alias name of the font to find. */ + const char *name) /* Name or alias name of the font to find. */ { const MacFontFamily * familyPtr; char ** aliases; @@ -2165,24 +1761,24 @@ FindFontFamilyOrAlias( familyPtr = FindFontFamily(name); if (familyPtr != NULL) { - return familyPtr; + return familyPtr; } aliases = TkFontGetAliasList(name); if (aliases != NULL) { - for (i = 0; aliases[i] != NULL; i++) { - familyPtr = FindFontFamily(aliases[i]); - if (familyPtr != NULL) { - return familyPtr; - } - } + for (i = 0; aliases[i] != NULL; i++) { + familyPtr = FindFontFamily(aliases[i]); + if (familyPtr != NULL) { + return familyPtr; + } + } } return NULL; } - + static const MacFontFamily * FindFontFamilyOrAliasOrFallback( - const char * name) /* Name or alias name of the font to find. */ + const char *name) /* Name or alias name of the font to find. */ { const MacFontFamily * familyPtr; const char * fallback; @@ -2191,36 +1787,36 @@ FindFontFamilyOrAliasOrFallback( familyPtr = FindFontFamilyOrAlias(name); if (familyPtr != NULL) { - return familyPtr; + return familyPtr; } fallbacks = TkFontGetFallbacks(); for (i = 0; fallbacks[i] != NULL; i++) { - for (j = 0; (fallback = fallbacks[i][j]) != NULL; j++) { - if (strcasecmp(name, fallback) == 0) { - for (j = 0; (fallback = fallbacks[i][j]) != NULL; j++) { - familyPtr = FindFontFamilyOrAlias(fallback); - if (familyPtr != NULL) { - return familyPtr; - } - } - } - break; /* benny: This "break" is a carry-over from - * tkMacOSXFont.c, but what is actually its purpose - * ???? */ - } + for (j = 0; (fallback = fallbacks[i][j]) != NULL; j++) { + if (strcasecmp(name, fallback) == 0) { + for (j = 0; (fallback = fallbacks[i][j]) != NULL; j++) { + familyPtr = FindFontFamilyOrAlias(fallback); + if (familyPtr != NULL) { + return familyPtr; + } + } + } + break; /* benny: This "break" is a carry-over from + * tkMacOSXFont.c, but what is actually its purpose + * ???? */ + } } /* - * FIXME: We would have liked to recover by re-enumerating fonts. But + * FIXME: We would have liked to recover by re-enumerating fonts. But * that doesn't work, because Carbon seems to cache the inital list of - * fonts. Fonts newly installed don't show up with + * fonts. Fonts newly installed don't show up with * FMCreateFontFamilyIterator()/FMGetNextFontFamily() without a restart - * of the app. Similar problem with fonts removed. + * of the app. Similar problem with fonts removed. */ #ifdef TK_MAC_DEBUG_FONTS - fprintf(stderr, "Font family '%s': Not found\n", name); + TkMacOSXDbgMsg("Font family '%s' not found", name); #endif return NULL; @@ -2231,16 +1827,16 @@ FindFontFamilyOrAliasOrFallback( * * InitFontFamilies -- * - * Helper to TkpFontPkgInit. Use the Font Manager to fill in the - * familyList global array. + * Helper to TkpFontPkgInit. Use the Font Manager to fill in the + * familyList global array. * * Results: * - * None. + * None. * * Side effects: * - * Allocates memory. + * Allocates memory. * *------------------------------------------------------------------------- */ @@ -2248,32 +1844,58 @@ FindFontFamilyOrAliasOrFallback( static void InitFontFamilies(void) { - OSStatus err; + FMFontFamily fontFamily; + Str255 fontName; + SInt16 fontSize; + Style fontStyle; /* * Has this been called before? */ if (familyListNextFree > 0) { - return; + return; } - err = ATSFontFamilyApplyFunction(FontFamilyEnumCallback,NULL); -#ifdef TK_MAC_DEBUG_FONTS - if (err != noErr) { - fprintf(stderr, "ATSFontFamilyApplyFunction(): Error %d\n", (int) err); - } -#endif + ChkErr(ATSFontFamilyApplyFunction, FontFamilyEnumCallback,NULL); - AddFontFamily(APPLFONT_NAME, GetAppFont()); - AddFontFamily(SYSTEMFONT_NAME, GetSysFont()); + if (GetThemeFontAndFamily(kThemeSystemFont, &fontFamily, fontName, + &fontSize, &fontStyle) == noErr) { + AddFontFamily(SYSTEMFONT_NAME, fontFamily); + } + if (GetThemeFontAndFamily(kThemeApplicationFont, &fontFamily, fontName, + &fontSize, &fontStyle) == noErr) { + AddFontFamily(APPLFONT_NAME, fontFamily); + } + if (GetThemeFontAndFamily(kThemeMenuItemFont, &fontFamily, fontName, + &fontSize, &fontStyle) == noErr) { + AddFontFamily(MENUITEMFONT_NAME, fontFamily); + } SortFontFamilies(); } + +/* + *------------------------------------------------------------------------- + * + * FontFamilyEnumCallback -- + * + * Callback for ATSFontFamilyApplyFunction(). + * + * Results: + * + * noErr. + * + * Side effects: + * + * None. + * + *------------------------------------------------------------------------- + */ static OSStatus FontFamilyEnumCallback( - ATSFontFamilyRef family, + ATSFontFamilyRef family, void *refCon) { OSStatus err; @@ -2281,42 +1903,41 @@ FontFamilyEnumCallback( (void) refCon; - err = GetFontFamilyName(family, name, sizeof(name)); + err = ChkErr(GetFontFamilyName, family, name, sizeof(name)); if (err == noErr) { - AddFontFamily(name, family); + AddFontFamily(name, family); } return noErr; } - /* *------------------------------------------------------------------------- * * GetFontFamilyName -- * - * Use the Font Manager to get the name of a given FMFontfamily. This - * currently gets the standard, non-localized QuickDraw name. Other - * names would be possible, see docs for ATSUFindFontName for a - * selection. The MacOSX font selector seems to use the localized - * family name given by ATSUFindFontName(kFontFamilyName), but that API - * doesn't give us a name at all for some fonts. + * Use the Font Manager to get the name of a given FMFontfamily. This + * currently gets the standard, non-localized QuickDraw name. Other + * names would be possible, see docs for ATSUFindFontName for a + * selection. The MacOSX font selector seems to use the localized + * family name given by ATSUFindFontName(kFontFamilyName), but that API + * doesn't give us a name at all for some fonts. * * Results: - * An OS error code, noErr on success. name is filled with the - * resulting name. + * An OS error code, noErr on success. name is filled with the + * resulting name. * * Side effects: - * None. + * None. * *------------------------------------------------------------------------- */ static OSStatus GetFontFamilyName( - FMFontFamily fontFamily, /* The font family for which to find the - * name. */ - char * name, int numBytes) /* Filled with the result. */ + FMFontFamily fontFamily, /* The font family for which to find the + * name. */ + char * name, int numBytes) /* Filled with the result. */ { OSStatus err; Str255 nativeName; @@ -2326,13 +1947,9 @@ GetFontFamilyName( nativeName[0] = 0; name[0] = 0; - - err = FMGetFontFamilyName(fontFamily, nativeName); + err = ChkErr(FMGetFontFamilyName, fontFamily, nativeName); if (err != noErr) { -#ifdef TK_MAC_DEBUG_FONTS - fprintf(stderr, "FMGetFontFamilyName(): Error %d\n", (int) err); -#endif - return err; + return err; } /* @@ -2341,36 +1958,25 @@ GetFontFamilyName( */ encoding = kTextEncodingMacRoman; - err = FMGetFontFamilyTextEncoding(fontFamily, &encoding); -#ifdef TK_MAC_DEBUG_FONTS - if (err != noErr) { - fprintf(stderr, "FMGetFontFamilyTextEncoding(): Error %d\n", (int) err); - } -#endif - + ChkErr(FMGetFontFamilyTextEncoding, fontFamily, &encoding); nameencoding = encoding; - err = RevertTextEncodingToScriptInfo(encoding, &nameencoding, NULL, NULL); -#ifdef TK_MAC_DEBUG_FONTS - if (err != noErr) { - fprintf(stderr, "RevertTextEncodingToScriptInfo(): Error %d\n", - (int) err); - } -#endif + ChkErr(RevertTextEncodingToScriptInfo, encoding, &nameencoding, NULL, + NULL); /* - * Note: We could use Tcl facilities to do the re-encoding here. We'd + * Note: We could use Tcl facilities to do the re-encoding here. We'd * have to maintain tables to map OS encoding codes to Tcl encoding names - * like tkMacOSXFont.c did. Using native re-encoding directly instead is - * a lot easier and future-proof than that. There is one snag, though: I - * have seen CFStringGetCString() crash with invalid encoding ids. But + * like tkMacOSXFont.c did. Using native re-encoding directly instead is + * a lot easier and future-proof than that. There is one snag, though: I + * have seen CFStringGetCString() crash with invalid encoding ids. But * than if that happens it would be a bug in * FMGetFontFamilyTextEncoding() or RevertTextEncodingToScriptInfo(). */ cfString = CFStringCreateWithPascalStringNoCopy( - NULL, nativeName, nameencoding, kCFAllocatorNull); + NULL, nativeName, nameencoding, kCFAllocatorNull); CFStringGetCString( - cfString, name, numBytes, kCFStringEncodingUTF8); + cfString, name, numBytes, kCFStringEncodingUTF8); CFRelease(cfString); return noErr; @@ -2381,41 +1987,39 @@ GetFontFamilyName( * * FindFontFamily -- * - * Find the font family with the given name in the global familyList. - * Uses bsearch() for convenient access. Comparision is done - * non-case-sensitively with CompareFontFamilies() which see. + * Find the font family with the given name in the global familyList. + * Uses bsearch() for convenient access. Comparision is done + * non-case-sensitively with CompareFontFamilies() which see. * * Results: * - * MacFontFamily: A pair of family id and the actual name registered for - * the font. + * MacFontFamily: A pair of family id and the actual name registered for + * the font. * * Side effects: * - * None. + * None. * * Assumption: * - * Requires the familyList array to be sorted. + * Requires the familyList array to be sorted. * *------------------------------------------------------------------------- */ static const MacFontFamily * FindFontFamily( - const char * name) /* The family name. Note: Names are compared - * non-case-sensitive. */ + const char *name) /* The family name. Note: Names are compared + * non-case-sensitive. */ { const MacFontFamily key = {name,-1}; if(familyListMaxValid <= 0) { - return NULL; + return NULL; } - return bsearch( - &key, - familyList, familyListMaxValid, sizeof(*familyList), - CompareFontFamilies); + return bsearch(&key, familyList, familyListMaxValid, sizeof(*familyList), + CompareFontFamilies); } /* @@ -2423,15 +2027,13 @@ FindFontFamily( * * EnumFontFamilies -- * - * Create a Tcl list with the registered names in the global familyList. + * Create a Tcl list with the registered names in the global familyList. * * Results: - * - * A Tcl list of names. + * A Tcl list of names. * * Side effects: - * - * None. + * None. * *------------------------------------------------------------------------- */ @@ -2444,8 +2046,8 @@ EnumFontFamilies(void) tclList = Tcl_NewListObj(0, NULL); for (i=0; i= familyListSize) { - familyListSize += 100; - familyList = (MacFontFamily *) ckrealloc( - (void*) familyList, - familyListSize * sizeof(*familyList)); + familyListSize += 100; + familyList = (MacFontFamily *) ckrealloc((void*) familyList, + familyListSize * sizeof(*familyList)); } familyPtr = familyList + familyListNextFree; @@ -2499,18 +2100,18 @@ AddFontFamily( * * SortFontFamilies -- * - * Sort the entries in familyList. Only after calling - * SortFontFamilies(), the new families registered with AddFontFamily() - * are actually available for FindFontFamily(), because FindFontFamily() - * requires the array to be sorted. + * Sort the entries in familyList. Only after calling + * SortFontFamilies(), the new families registered with AddFontFamily() + * are actually available for FindFontFamily(), because FindFontFamily() + * requires the array to be sorted. * * Results: * - * None. + * None. * * Side effects: * - * familyList is sorted and familyListMaxValid is updated. + * familyList is sorted and familyListMaxValid is updated. * *------------------------------------------------------------------------- */ @@ -2519,8 +2120,8 @@ static void SortFontFamilies(void) { if (familyListNextFree > 0) { - qsort( familyList, familyListNextFree, sizeof(*familyList), - CompareFontFamilies); + qsort(familyList, familyListNextFree, sizeof(*familyList), + CompareFontFamilies); } familyListMaxValid = familyListNextFree; } @@ -2530,21 +2131,19 @@ SortFontFamilies(void) * * CompareFontFamilies -- * - * Comparison function used by SortFontFamilies() and FindFontFamily(). + * Comparison function used by SortFontFamilies() and FindFontFamily(). * * Results: + * Result as required to generate a stable sort order for bsearch() and + * qsort(). The ordering is not case-sensitive as far as + * Tcl_UtfNcasecmp() (which see) can provide that. * - * Result as required to generate a stable sort order for bsearch() and - * qsort(). The ordering is not case-sensitive as far as - * Tcl_UtfNcasecmp() (which see) can provide that. - * - * Note: It would be faster to compare first the length and the actual - * strings only as a tie-breaker, but than the ordering wouldn't look so - * pretty in [font families] ;-). + * Note: It would be faster to compare first the length and the actual + * strings only as a tie-breaker, but than the ordering wouldn't look so + * pretty in [font families] ;-). * * Side effects: - * - * None. + * None. * *------------------------------------------------------------------------- */ @@ -2556,9 +2155,7 @@ CompareFontFamilies( { const char * name1; const char * name2; - int len1; - int len2; - int diff; + int len1, len2, diff; name1 = ((const MacFontFamily *) vp1)->name; name2 = ((const MacFontFamily *) vp2)->name; @@ -2576,36 +2173,34 @@ CompareFontFamilies( * * AddString -- * - * Helper for AddFontFamily(). Allocates a string in the one-shot - * allocator. + * Helper for AddFontFamily(). Allocates a string in the one-shot + * allocator. * * Results: - * - * A duplicated string in the one-shot allocator. + * A duplicated string in the one-shot allocator. * * Side effects: - * - * May allocate a new memory block. + * May allocate a new memory block. * *------------------------------------------------------------------------- */ static const char * AddString( - const char * in) /* String to add, zero-terminated. */ + const char *in) /* String to add, zero-terminated. */ { int len; - char * result; - + char *result; + len = strlen(in) +1; if (stringMemory == NULL - || (stringMemory->nextFree+len) > STRING_BLOCK_MAX ) { - StringBlock * newblock = - (StringBlock *) ckalloc(sizeof(StringBlock)); - newblock->next = stringMemory; - newblock->nextFree = 0; - stringMemory = newblock; + || (stringMemory->nextFree+len) > STRING_BLOCK_MAX) { + StringBlock * newblock = (StringBlock *) ckalloc(sizeof(StringBlock)); + + newblock->next = stringMemory; + newblock->nextFree = 0; + stringMemory = newblock; } result = stringMemory->strings + stringMemory->nextFree; @@ -2621,27 +2216,27 @@ AddString( * * TkMacOSXIsCharacterMissing -- * - * Given a tkFont and a character determine whether the character has - * a glyph defined in the font or not. + * Given a tkFont and a character determine whether the character has + * a glyph defined in the font or not. * * Results: - * Returns a 1 if the character is missing, a 0 if it is not. + * Returns a 1 if the character is missing, a 0 if it is not. * * Side effects: - * None. + * None. * *--------------------------------------------------------------------------- */ int TkMacOSXIsCharacterMissing( - Tk_Font tkfont, /* The font we are looking in. */ - unsigned int searchChar) /* The character we are looking for. */ + Tk_Font tkfont, /* The font we are looking in. */ + unsigned int searchChar) /* The character we are looking for. */ { /* Background: This function is private and only used in * tkMacOSXMenu.c:FindMarkCharacter(). * - * We could use ATSUMatchFont() to implement. We'd have to change the + * We could use ATSUMatchFont() to implement. We'd have to change the * definition of the encoding of the parameter searchChar from MacRoman * to UniChar for that. * @@ -2656,30 +2251,27 @@ TkMacOSXIsCharacterMissing( * * TkMacOSXInitControlFontStyle -- * - * This procedure sets up the appropriate ControlFontStyleRec - * for a Mac control. + * This procedure sets up the appropriate ControlFontStyleRec + * for a Mac control. * * Results: - * None. + * None. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ void TkMacOSXInitControlFontStyle( - Tk_Font tkfont, /* Tk font object to use for the control. */ - ControlFontStylePtr fsPtr) /* The style object to configure. */ + Tk_Font tkfont, /* Tk font object to use for the control. */ + ControlFontStylePtr fsPtr) /* The style object to configure. */ { - const MacFont * fontPtr; - fontPtr = (MacFont *) tkfont; - fsPtr->flags = - kControlUseFontMask| - kControlUseSizeMask| - kControlUseFaceMask| - kControlUseJustMask; + const MacFont * fontPtr = (MacFont *) tkfont; + + fsPtr->flags = kControlUseFontMask | kControlUseSizeMask | + kControlUseFaceMask | kControlUseJustMask; fsPtr->font = fontPtr->qdFont; fsPtr->size = fontPtr->qdSize; fsPtr->style = fontPtr->qdStyle; @@ -2691,46 +2283,46 @@ TkMacOSXInitControlFontStyle( * * TkMacOSXUseAntialiasedText -- * - * Enables or disables application-wide use of antialiased text (where - * available). Sets up a linked Tcl global variable to allow - * disabling of antialiased text from tcl. - * The possible values for this variable are: + * Enables or disables application-wide use of antialiased text (where + * available). Sets up a linked Tcl global variable to allow + * disabling of antialiased text from tcl. + * The possible values for this variable are: * - * -1 - Use system default as configurable in "System Preferences" -> - * "General". - * 0 - Unconditionally disable antialiasing. - * 1 - Unconditionally enable antialiasing. + * -1 - Use system default as configurable in "System Preferences" -> + * "General". + * 0 - Unconditionally disable antialiasing. + * 1 - Unconditionally enable antialiasing. * * Results: * - * TCL_OK. + * TCL_OK. * * Side effects: * - * None. + * None. * *---------------------------------------------------------------------- */ MODULE_SCOPE int TkMacOSXUseAntialiasedText( - Tcl_Interp * interp, /* The Tcl interpreter to receive the - * variable .*/ - int enable) /* Initial value. */ + Tcl_Interp * interp, /* The Tcl interpreter to receive the + * variable.*/ + int enable) /* Initial value. */ { static Boolean initialized = FALSE; - if(!initialized) { - initialized = TRUE; - - if (Tcl_CreateNamespace(interp, "::tk::mac", NULL, NULL) == NULL) { - Tcl_ResetResult(interp); - } - if (Tcl_LinkVar(interp, "::tk::mac::antialiasedtext", - (char *) &antialiasedTextEnabled, - TCL_LINK_INT) != TCL_OK) { - Tcl_ResetResult(interp); - } + if (!initialized) { + initialized = TRUE; + + if (Tcl_CreateNamespace(interp, "::tk::mac", NULL, NULL) == NULL) { + Tcl_ResetResult(interp); + } + if (Tcl_LinkVar(interp, "::tk::mac::antialiasedtext", + (char *) &antialiasedTextEnabled, + TCL_LINK_INT) != TCL_OK) { + Tcl_ResetResult(interp); + } } antialiasedTextEnabled = enable; return TCL_OK; diff --git a/macosx/tkMacOSXFont.h b/macosx/tkMacOSXFont.h index 22555a5..56c0bbc 100644 --- a/macosx/tkMacOSXFont.h +++ b/macosx/tkMacOSXFont.h @@ -1,19 +1,22 @@ /* * tkMacOSXFont.h -- * - * Private functions and structs exported from tkMacOSXFont.c - * for use in ATSU specific extensions. + * Contains the Macintosh implementation of the platform-independant + * font package interface. * - * Copyright 2002-2004 Benjamin Riefenstahl, Benjamin.Riefenstahl@epost.de + * Copyright (c) 1990-1994 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2006-2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXFont.h,v 1.4 2006/04/28 06:02:48 das Exp $ + * RCS: @(#) $Id: tkMacOSXFont.h,v 1.5 2007/04/23 21:24:33 das Exp $ */ -#ifndef TKMACOSXFONT_H -#define TKMACOSXFONT_H 1 +#ifndef TKMACOSXFONT_H +#define TKMACOSXFONT_H 1 #include "tkFont.h" @@ -22,93 +25,10 @@ #endif /* - * Switches - */ - -#define TK_MAC_USE_QUARZ 1 - -/* - * Types - */ - -/* - * The following structure represents our Macintosh-specific implementation - * of a font object. - */ - -typedef struct { - TkFont font; /* Stuff used by generic font package. Must - * be first in structure. */ - - /* - * The ATSU view of the font and other text properties. Used for drawing - * and measuring. - */ - - ATSUFontID atsuFontId; /* == FMFont. */ - ATSUTextLayout atsuLayout; /* ATSU layout object, representing the whole - * text that ATSU sees with some option - * bits. */ - ATSUStyle atsuStyle; /* ATSU style object, representing a run of - * text with the same properties. */ - - /* - * The QuickDraw view of the font. Used to configure controls. - */ - - FMFontFamily qdFont; /* == FMFontFamilyId, Carbon replacement for - * QD face numbers. */ - short qdSize; /* Font size in points. */ - short qdStyle; /* QuickDraw style bits. */ -} TkMacOSXFont; - - -#if TK_MAC_USE_QUARZ - -/* - * To use Quarz drawing we need some additional context. FIXME: We would - * have liked to use the similar functions from tkMacOSXDraw.c to do this - * (TkMacOSXSetUpCGContext(), etc), but a) those don't quite work for us - * (e.g. we can't use a simple upside-down coordinate system transformation, - * as we don't want upside-down characters ;-), and b) we don't have the - * necessary context information (MacDrawable), that we need as parameter for - * those functions. So I just cobbled together a limited edition, getting - * the necessary parameters from the current QD GraphPort. - */ - -typedef struct { - CGContextRef cgContext; /* Quarz context. */ - CGrafPtr graphPort; /* QD graph port to which this belongs. - * Needed for releasing cgContext. */ - Rect portRect; /* Cached size of port. */ -} TkMacOSXFontDrawingContext; - -#else /* ! TK_MAC_USE_QUARZ */ - -/* - * Just a dummy, so we don't have to #ifdef the parameter lists of functions - * that use this. - */ - -typedef struct {} DrawingContext; - -#endif /* ? TK_MAC_USE_QUARZ */ - -/* * Function prototypes */ -MODULE_SCOPE void TkMacOSXLayoutSetString(const TkMacOSXFont * fontPtr, - const TkMacOSXFontDrawingContext *drawingContextPtr, - const UniChar * uchars, int ulen); -MODULE_SCOPE void TkMacOSXInitControlFontStyle(Tk_Font tkfont, - ControlFontStylePtr fsPtr); - -#if TK_MAC_USE_QUARZ -MODULE_SCOPE void TkMacOSXQuarzStartDraw( - TkMacOSXFontDrawingContext * contextPtr); -MODULE_SCOPE void TkMacOSXQuarzEndDraw( - TkMacOSXFontDrawingContext * contextPtr); -#endif /* TK_MAC_USE_QUARZ */ +MODULE_SCOPE void TkMacOSXInitControlFontStyle(Tk_Font tkfont, + ControlFontStylePtr fsPtr); -#endif /*TKMACOSXFONT_H*/ +#endif /*TKMACOSXFONT_H*/ diff --git a/macosx/tkMacOSXHLEvents.c b/macosx/tkMacOSXHLEvents.c index 4355316..850d80f 100644 --- a/macosx/tkMacOSXHLEvents.c +++ b/macosx/tkMacOSXHLEvents.c @@ -1,8 +1,8 @@ -/* +/* * tkMacOSXHLEvents.c -- * - * Implements high level event support for the Macintosh. Currently, - * the only event that really does anything is the Quit event. + * Implements high level event support for the Macintosh. Currently, + * the only event that really does anything is the Quit event. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXHLEvents.c,v 1.12 2006/05/12 18:18:36 das Exp $ + * RCS: @(#) $Id: tkMacOSXHLEvents.c,v 1.13 2007/04/23 21:24:33 das Exp $ */ #include "tkMacOSXInt.h" @@ -20,12 +20,12 @@ * This is a Tcl_Event structure that the Quit AppleEvent handler * uses to schedule the ReallyKillMe function. */ - + typedef struct KillEvent { - Tcl_Event header; /* Information that is standard for - * all events. */ - Tcl_Interp *interp; /* Interp that was passed to the - * Quit AppleEvent */ + Tcl_Event header; /* Information that is standard for + * all events. */ + Tcl_Interp *interp; /* Interp that was passed to the + * Quit AppleEvent */ } KillEvent; /* @@ -49,68 +49,66 @@ static OSErr PrefsHandler(const AppleEvent * event, AppleEvent * reply, static int MissedAnyParameters(const AppleEvent *theEvent); static int ReallyKillMe(Tcl_Event *eventPtr, int flags); -static OSErr FSRefToDString(const FSRef *fsref, Tcl_DString *ds); +static OSStatus FSRefToDString(const FSRef *fsref, Tcl_DString *ds); /* *---------------------------------------------------------------------- * * TkMacOSXInitAppleEvents -- * - * Initilize the Apple Events on the Macintosh. This registers the - * core event handlers. + * Initilize the Apple Events on the Macintosh. This registers the + * core event handlers. * * Results: - * None. + * None. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ -void +void TkMacOSXInitAppleEvents( - Tcl_Interp *interp) /* Interp to handle basic events. */ + Tcl_Interp *interp) /* Interp to handle basic events. */ { - OSErr err; - AEEventHandlerUPP OappHandlerUPP, RappHandlerUPP, OdocHandlerUPP, - PrintHandlerUPP, QuitHandlerUPP, ScriptHandlerUPP, - PrefsHandlerUPP; + AEEventHandlerUPP OappHandlerUPP, RappHandlerUPP, OdocHandlerUPP, + PrintHandlerUPP, QuitHandlerUPP, ScriptHandlerUPP, PrefsHandlerUPP; static Boolean initialized = FALSE; if (!initialized) { - initialized = TRUE; + initialized = TRUE; /* * Install event handlers for the core apple events. */ QuitHandlerUPP = NewAEEventHandlerUPP(QuitHandler); - err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, + ChkErr(AEInstallEventHandler, kCoreEventClass, kAEQuitApplication, QuitHandlerUPP, (long) interp, false); OappHandlerUPP = NewAEEventHandlerUPP(OappHandler); - err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, + ChkErr(AEInstallEventHandler, kCoreEventClass, kAEOpenApplication, OappHandlerUPP, (long) interp, false); RappHandlerUPP = NewAEEventHandlerUPP(RappHandler); - err = AEInstallEventHandler(kCoreEventClass, kAEReopenApplication, + ChkErr(AEInstallEventHandler, kCoreEventClass, kAEReopenApplication, RappHandlerUPP, (long) interp, false); OdocHandlerUPP = NewAEEventHandlerUPP(OdocHandler); - err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, + ChkErr(AEInstallEventHandler, kCoreEventClass, kAEOpenDocuments, OdocHandlerUPP, (long) interp, false); PrintHandlerUPP = NewAEEventHandlerUPP(PrintHandler); - err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, + ChkErr(AEInstallEventHandler, kCoreEventClass, kAEPrintDocuments, PrintHandlerUPP, (long) interp, false); PrefsHandlerUPP = NewAEEventHandlerUPP(PrefsHandler); - err = AEInstallEventHandler(kCoreEventClass, kAEShowPreferences, + ChkErr(AEInstallEventHandler, kCoreEventClass, kAEShowPreferences, PrefsHandlerUPP, (long) interp, false); if (interp) { ScriptHandlerUPP = NewAEEventHandlerUPP(ScriptHandler); - err = AEInstallEventHandler(kAEMiscStandards, kAEDoScript, + ChkErr(AEInstallEventHandler, kAEMiscStandards, kAEDoScript, ScriptHandlerUPP, (long) interp, false); } } @@ -121,13 +119,13 @@ TkMacOSXInitAppleEvents( * * TkMacOSXDoHLEvent -- * - * Dispatch incomming highlevel events. + * Dispatch incomming highlevel events. * * Results: - * None. + * None. * * Side effects: - * Depends on the incoming event. + * Depends on the incoming event. * *---------------------------------------------------------------------- */ @@ -142,46 +140,63 @@ TkMacOSXDoHLEvent( /* *---------------------------------------------------------------------- * - * QuitHandler, OappHandler, etc. -- + * QuitHandler -- * - * These are the core Apple event handlers. + * This is the 'quit' core Apple event handler. * * Results: - * None. + * None. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ -static OSErr -QuitHandler ( + +OSErr +QuitHandler( const AppleEvent * event, AppleEvent * reply, long handlerRefcon) { Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon; KillEvent *eventPtr; - + if (interp) { /* * Call the exit command from the event loop, since you are not supposed - * to call ExitToShell in an Apple Event Handler. We put this at the head + * to call ExitToShell in an Apple Event Handler. We put this at the head * of Tcl's event queue because this message usually comes when the Mac is * shutting down, and we want to kill the shell as quickly as possible. */ - + eventPtr = (KillEvent *) ckalloc(sizeof(KillEvent)); eventPtr->header.proc = ReallyKillMe; eventPtr->interp = interp; - + Tcl_QueueEvent((Tcl_Event *) eventPtr, TCL_QUEUE_HEAD); } return noErr; } -static OSErr -OappHandler ( +/* + *---------------------------------------------------------------------- + * + * OappHandler -- + * + * This is the 'oapp' core Apple event handler. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +OSErr +OappHandler( const AppleEvent * event, AppleEvent * reply, long handlerRefcon) @@ -196,8 +211,24 @@ OappHandler ( return noErr; } -static OSErr -RappHandler ( +/* + *---------------------------------------------------------------------- + * + * RappHandler -- + * + * This is the 'rapp' core Apple event handler. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +OSErr +RappHandler( const AppleEvent * event, AppleEvent * reply, long handlerRefcon) @@ -205,18 +236,34 @@ RappHandler ( Tcl_CmdInfo dummy; Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon; ProcessSerialNumber thePSN = {0, kCurrentProcess}; - OSStatus status = SetFrontProcess(&thePSN); - + OSStatus err = ChkErr(SetFrontProcess, &thePSN); + if (interp && Tcl_GetCommandInfo(interp, "::tk::mac::ReopenApplication", &dummy)) { Tcl_GlobalEval(interp, "::tk::mac::ReopenApplication"); } - return status; + return err; } -/* Called when the user selects 'Preferences...' in MacOS X */ -static OSErr -PrefsHandler ( +/* + *---------------------------------------------------------------------- + * + * PrefsHandler -- + * + * This is the 'pref' core Apple event handler. + * Called when the user selects 'Preferences...' in MacOS X + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +OSErr +PrefsHandler( const AppleEvent * event, AppleEvent * reply, long handlerRefcon) @@ -231,8 +278,24 @@ PrefsHandler ( return noErr; } -static OSErr -OdocHandler ( +/* + *---------------------------------------------------------------------- + * + * OdocHandler -- + * + * This is the 'odoc' core Apple event handler. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +OSErr +OdocHandler( const AppleEvent * event, AppleEvent * reply, long handlerRefcon) @@ -240,7 +303,7 @@ OdocHandler ( Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon; AEDescList fileSpecList; FSRef file; - OSErr err; + OSStatus err; DescType type; Size actual; long count; @@ -255,56 +318,73 @@ OdocHandler ( * the open document procedure doesn't exist. */ - if ((interp == NULL) || - (Tcl_GetCommandInfo(interp, "::tk::mac::OpenDocument", &dummy)) == 0) { - return noErr; + if ((interp == NULL) || + (Tcl_GetCommandInfo(interp, "::tk::mac::OpenDocument", &dummy)) == 0) { + return noErr; } - + /* * If we get any errors wil retrieving our parameters * we just return with no error. */ - err = AEGetParamDesc(event, keyDirectObject, - typeAEList, &fileSpecList); + err = ChkErr(AEGetParamDesc, event, keyDirectObject, typeAEList, + &fileSpecList); if (err != noErr) { - return noErr; + return noErr; } err = MissedAnyParameters(event); if (err != noErr) { - return noErr; + return noErr; } - err = AECountItems(&fileSpecList, &count); + err = ChkErr(AECountItems, &fileSpecList, &count); if (err != noErr) { - return noErr; + return noErr; } Tcl_DStringInit(&command); Tcl_DStringAppend(&command, "::tk::mac::OpenDocument", -1); for (index = 1; index <= count; index++) { - err = AEGetNthPtr(&fileSpecList, index, typeFSRef, - &keyword, &type, (Ptr) &file, sizeof(FSRef), &actual); - if ( err != noErr ) { - continue; - } - - err = FSRefToDString(&file, &pathName); - if (err == noErr) { - Tcl_DStringAppendElement(&command, Tcl_DStringValue(&pathName)); - Tcl_DStringFree(&pathName); - } + err = ChkErr(AEGetNthPtr, &fileSpecList, index, typeFSRef, + &keyword, &type, (Ptr) &file, sizeof(FSRef), &actual); + if ( err != noErr ) { + continue; + } + + err = ChkErr(FSRefToDString, &file, &pathName); + if (err == noErr) { + Tcl_DStringAppendElement(&command, Tcl_DStringValue(&pathName)); + Tcl_DStringFree(&pathName); + } } - - Tcl_GlobalEval(interp, Tcl_DStringValue(&command)); + + Tcl_EvalEx(interp, Tcl_DStringValue(&command), Tcl_DStringLength(&command), + TCL_EVAL_GLOBAL); Tcl_DStringFree(&command); return noErr; } -static OSErr -PrintHandler ( +/* + *---------------------------------------------------------------------- + * + * PrintHandler -- + * + * This is the 'pdoc' core Apple event handler. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +OSErr +PrintHandler( const AppleEvent * event, AppleEvent * reply, long handlerRefcon) @@ -312,7 +392,7 @@ PrintHandler ( Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon; AEDescList fileSpecList; FSRef file; - OSErr err; + OSStatus err; DescType type; Size actual; long count; @@ -327,49 +407,50 @@ PrintHandler ( * the print document procedure doesn't exist. */ - if ((interp == NULL) || - (Tcl_GetCommandInfo(interp, "::tk::mac::PrintDocument", &dummy)) == 0) { - return noErr; + if ((interp == NULL) || + (Tcl_GetCommandInfo(interp, "::tk::mac::PrintDocument", &dummy)) == 0) { + return noErr; } - + /* * If we get any errors wil retrieving our parameters * we just return with no error. */ - err = AEGetParamDesc(event, keyDirectObject, - typeAEList, &fileSpecList); + err = ChkErr(AEGetParamDesc, event, keyDirectObject, typeAEList, + &fileSpecList); if (err != noErr) { - return noErr; + return noErr; } - err = MissedAnyParameters(event); + err = ChkErr(MissedAnyParameters, event); if (err != noErr) { - return noErr; + return noErr; } - err = AECountItems(&fileSpecList, &count); + err = ChkErr(AECountItems, &fileSpecList, &count); if (err != noErr) { - return noErr; + return noErr; } Tcl_DStringInit(&command); Tcl_DStringAppend(&command, "::tk::mac::PrintDocument", -1); for (index = 1; index <= count; index++) { - err = AEGetNthPtr(&fileSpecList, index, typeFSRef, - &keyword, &type, (Ptr) &file, sizeof(FSRef), &actual); - if ( err != noErr ) { - continue; - } - - err = FSRefToDString(&file, &pathName); - if (err == noErr) { - Tcl_DStringAppendElement(&command, Tcl_DStringValue(&pathName)); - Tcl_DStringFree(&pathName); - } + err = ChkErr(AEGetNthPtr, &fileSpecList, index, typeFSRef, &keyword, + &type, (Ptr) &file, sizeof(FSRef), &actual); + if ( err != noErr ) { + continue; + } + + err = ChkErr(FSRefToDString, &file, &pathName); + if (err == noErr) { + Tcl_DStringAppendElement(&command, Tcl_DStringValue(&pathName)); + Tcl_DStringFree(&pathName); + } } - - Tcl_GlobalEval(interp, Tcl_DStringValue(&command)); + + Tcl_EvalEx(interp, Tcl_DStringValue(&command), Tcl_DStringLength(&command), + TCL_EVAL_GLOBAL); Tcl_DStringFree(&command); return noErr; @@ -380,24 +461,24 @@ PrintHandler ( * * ScriptHandler -- * - * This handler process the script event. + * This handler process the script event. * * Results: - * Schedules the given event to be processed. + * Schedules the given event to be processed. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ -static OSErr -ScriptHandler ( +OSErr +ScriptHandler( const AppleEvent * event, AppleEvent * reply, long handlerRefcon) { - OSErr theErr; + OSStatus theErr; AEDescList theDesc; int tclErr = -1; Tcl_Interp *interp; @@ -409,98 +490,100 @@ ScriptHandler ( * The do script event receives one parameter that should be data or a file. */ theErr = AEGetParamDesc(event, keyDirectObject, typeWildCard, - &theDesc); + &theDesc); if (theErr != noErr) { - sprintf(errString, "AEDoScriptHandler: GetParamDesc error %d", theErr); - theErr = AEPutParamPtr(reply, keyErrorString, typeChar, errString, - strlen(errString)); + sprintf(errString, "AEDoScriptHandler: GetParamDesc error %ld", + theErr); + theErr = AEPutParamPtr(reply, keyErrorString, typeChar, errString, + strlen(errString)); } else if (MissedAnyParameters(event)) { - sprintf(errString, "AEDoScriptHandler: extra parameters"); - AEPutParamPtr(reply, keyErrorString, typeChar, errString, - strlen(errString)); - theErr = -1771; + sprintf(errString, "AEDoScriptHandler: extra parameters"); + AEPutParamPtr(reply, keyErrorString, typeChar, errString, + strlen(errString)); + theErr = -1771; } else { - if (theDesc.descriptorType == (DescType)typeChar) { - Tcl_DString encodedText; - short i; - Size size; - char * data; - - size = AEGetDescDataSize(&theDesc); - - data = (char *)ckalloc(size + 1); - if ( !data ) { - theErr = -1771; - } - else { - AEGetDescData(&theDesc,data,size); - data [ size ] = 0; - for (i = 0; i < size; i++) - if (data[i] == '\r') - data[i] = '\n'; - AEReplaceDescData(theDesc.descriptorType, data, - size + 1, &theDesc); - } - Tcl_ExternalToUtfDString(NULL, data, size, - &encodedText); - tclErr = Tcl_GlobalEval(interp, Tcl_DStringValue(&encodedText)); - Tcl_DStringFree(&encodedText); - } else if (theDesc.descriptorType == (DescType)typeAlias) { - Boolean dummy; - FSRef file; - AliasPtr alias; - Size theSize; - - theSize = AEGetDescDataSize(&theDesc); - alias = (AliasPtr) ckalloc(theSize); - if (alias) { - AEGetDescData (&theDesc, alias, theSize); - - theErr = FSResolveAlias(NULL, &alias, - &file, &dummy); - ckfree((char*)alias); - } else { - theErr = memFullErr; - } - if (theErr == noErr) { - Tcl_DString scriptName; - theErr = FSRefToDString(&file, &scriptName); - if (theErr == noErr) { - Tcl_EvalFile(interp, Tcl_DStringValue(&scriptName)); - Tcl_DStringFree(&scriptName); - } - } else { - sprintf(errString, "AEDoScriptHandler: file not found"); - AEPutParamPtr(reply, keyErrorString, typeChar, - errString, strlen(errString)); - } - } else { - sprintf(errString, - "AEDoScriptHandler: invalid script type '%-4.4s', must be 'alis' or 'TEXT'", - (char *)(&theDesc.descriptorType)); - AEPutParamPtr(reply, keyErrorString, typeChar, - errString, strlen(errString)); - theErr = -1770; - } + if (theDesc.descriptorType == (DescType)typeChar) { + Tcl_DString encodedText; + short i; + Size size; + char * data; + + size = AEGetDescDataSize(&theDesc); + + data = (char *)ckalloc(size + 1); + if ( !data ) { + theErr = -1771; + } + else { + AEGetDescData(&theDesc,data,size); + data [ size ] = 0; + for (i = 0; i < size; i++) + if (data[i] == '\r') + data[i] = '\n'; + AEReplaceDescData(theDesc.descriptorType, data, + size + 1, &theDesc); + } + Tcl_ExternalToUtfDString(NULL, data, size, + &encodedText); + tclErr = Tcl_EvalEx(interp, Tcl_DStringValue(&encodedText), + Tcl_DStringLength(&encodedText), TCL_EVAL_GLOBAL); + Tcl_DStringFree(&encodedText); + } else if (theDesc.descriptorType == (DescType)typeAlias) { + Boolean dummy; + FSRef file; + AliasPtr alias; + Size theSize; + + theSize = AEGetDescDataSize(&theDesc); + alias = (AliasPtr) ckalloc(theSize); + if (alias) { + AEGetDescData (&theDesc, alias, theSize); + + theErr = FSResolveAlias(NULL, &alias, + &file, &dummy); + ckfree((char*)alias); + } else { + theErr = memFullErr; + } + if (theErr == noErr) { + Tcl_DString scriptName; + theErr = FSRefToDString(&file, &scriptName); + if (theErr == noErr) { + Tcl_EvalFile(interp, Tcl_DStringValue(&scriptName)); + Tcl_DStringFree(&scriptName); + } + } else { + sprintf(errString, "AEDoScriptHandler: file not found"); + AEPutParamPtr(reply, keyErrorString, typeChar, + errString, strlen(errString)); + } + } else { + sprintf(errString, + "AEDoScriptHandler: invalid script type '%-4.4s', must be 'alis' or 'TEXT'", + (char *)(&theDesc.descriptorType)); + AEPutParamPtr(reply, keyErrorString, typeChar, + errString, strlen(errString)); + theErr = -1770; + } } /* * If we actually go to run Tcl code - put the result in the reply. */ if (tclErr >= 0) { - if (tclErr == TCL_OK) { - AEPutParamPtr(reply, keyDirectObject, typeChar, - Tcl_GetStringResult(interp), - strlen(Tcl_GetStringResult(interp))); - } else { - AEPutParamPtr(reply, keyErrorString, typeChar, - Tcl_GetStringResult(interp), - strlen(Tcl_GetStringResult(interp))); - AEPutParamPtr(reply, keyErrorNumber, typeInteger, - (Ptr) &tclErr, sizeof(int)); - } + if (tclErr == TCL_OK) { + AEPutParamPtr(reply, keyDirectObject, typeChar, + Tcl_GetStringResult(interp), + strlen(Tcl_GetStringResult(interp))); + } else { + AEPutParamPtr(reply, keyErrorString, typeChar, + Tcl_GetStringResult(interp), + strlen(Tcl_GetStringResult(interp))); + AEPutParamPtr(reply, keyErrorNumber, typeInteger, + (Ptr) &tclErr, sizeof(int)); + } } - + AEDisposeDesc(&theDesc); return theErr; @@ -511,22 +594,22 @@ ScriptHandler ( * * ReallyKillMe -- * - * This proc tries to kill the shell by running exit, - * called from an event scheduled by the "Quit" AppleEvent handler. + * This proc tries to kill the shell by running exit, + * called from an event scheduled by the "Quit" AppleEvent handler. * * Results: - * Runs the "exit" command which might kill the shell. + * Runs the "exit" command which might kill the shell. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ -static int +static int ReallyKillMe( Tcl_Event *eventPtr, - int flags) + int flags) { Tcl_Interp *interp = ((KillEvent *) eventPtr)->interp; Tcl_CmdInfo dummy; @@ -543,28 +626,28 @@ ReallyKillMe( * * MissedAnyParameters -- * - * Checks to see if parameters are still left in the event. + * Checks to see if parameters are still left in the event. * * Results: - * True or false. + * True or false. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ - -static int + +int MissedAnyParameters( const AppleEvent *theEvent) { DescType returnedType; Size actualSize; - OSErr err; + OSStatus err; + + err = ChkErr(AEGetAttributePtr, theEvent, keyMissedKeywordAttr, + typeWildCard, &returnedType, NULL, 0, &actualSize); - err = AEGetAttributePtr(theEvent, keyMissedKeywordAttr, typeWildCard, - &returnedType, NULL, 0, &actualSize); - return (err != errAEDescNotFound); } @@ -573,28 +656,28 @@ MissedAnyParameters( * * FSRefToDString -- * - * Get a POSIX path from an FSRef. + * Get a POSIX path from an FSRef. * * Results: - * In the parameter ds. + * In the parameter ds. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ -static OSErr +OSStatus FSRefToDString( const FSRef *fsref, Tcl_DString *ds) { UInt8 fileName[PATH_MAX+1]; - OSErr err; + OSStatus err; - err = FSRefMakePath(fsref, fileName, sizeof(fileName)); + err = ChkErr(FSRefMakePath, fsref, fileName, sizeof(fileName)); if (err == noErr) { - Tcl_ExternalToUtfDString(NULL, (char*) fileName, -1, ds); + Tcl_ExternalToUtfDString(NULL, (char*) fileName, -1, ds); } return err; } diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c index cde0be8..6625e4a 100644 --- a/macosx/tkMacOSXInit.c +++ b/macosx/tkMacOSXInit.c @@ -1,17 +1,17 @@ -/* +/* * tkMacOSXInit.c -- * - * This file contains Mac OS X -specific interpreter initialization - * functions. + * This file contains Mac OS X -specific interpreter initialization + * functions. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. - * Copyright (c) 2005-2006 Daniel A. Steffen + * Copyright (c) 2005-2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXInit.c,v 1.27 2007/04/21 19:06:38 hobbs Exp $ + * RCS: @(#) $Id: tkMacOSXInit.c,v 1.28 2007/04/23 21:24:33 das Exp $ */ #include "tkMacOSXInt.h" @@ -40,13 +40,13 @@ /* * The following structures are used to map the script/language codes of a * font to the name that should be passed to Tcl_GetEncoding() to obtain - * the encoding for that font. The set of numeric constants is fixed and + * the encoding for that font. The set of numeric constants is fixed and * defined by Apple. */ typedef struct Map { CFStringEncoding numKey; - char *strKey; + const char *strKey; } Map; static Map scriptMap[] = { @@ -82,7 +82,7 @@ static Map scriptMap[] = { {smEastEurRoman, "macCentEuro"}, {smVietnamese, "macVietnam"}, {smExtArabic, "macSindhi"}, - {0, NULL} + {0, NULL} }; Tcl_Encoding TkMacOSXCarbonEncoding = NULL; @@ -93,79 +93,60 @@ Tcl_Encoding TkMacOSXCarbonEncoding = NULL; */ static char scriptPath[PATH_MAX + 1] = ""; + /* *---------------------------------------------------------------------- * * TkpInit -- * - * Performs Mac-specific interpreter initialization related to the - * tk_library variable. + * Performs Mac-specific interpreter initialization related to the + * tk_library variable. * * Results: - * Returns a standard Tcl result. Leaves an error message or result - * in the interp's result. + * Returns a standard Tcl result. Leaves an error message or result + * in the interp's result. * * Side effects: - * Sets "tk_library" Tcl variable, runs "tk.tcl" script. + * Sets "tk_library" Tcl variable, runs "tk.tcl" script. * *---------------------------------------------------------------------- */ int -TkpInit(interp) - Tcl_Interp *interp; +TkpInit( + Tcl_Interp *interp) { static char tkLibPath[PATH_MAX + 1]; - static int tkMacOSXInitialized = false; + static int tkMacOSXInitialized = 0; Tk_MacOSXSetupTkNotifier(); - /* + /* * Since it is possible for TkInit to be called multiple times - * and we don't want to do the initialization multiple times + * and we don't want to do the following initialization multiple times * we protect against doing it more than once. */ - if (tkMacOSXInitialized == false) { + if (!tkMacOSXInitialized) { + int bundledExecutable = 0; + CFBundleRef bundleRef; + CFURLRef bundleUrl = NULL; CFStringEncoding encoding; - char *encodingStr = NULL; + const char *encodingStr = NULL; int i; - tkMacOSXInitialized = true; - - TkMacOSXInitAppleEvents(interp); - TkMacOSXInitCarbonEvents(interp); - TkMacOSXInitMenus(interp); - TkMacOSXUseAntialiasedText(interp, -1); - TkMacOSXInitCGDrawing(interp, TRUE, 0); - TkMacOSXInitKeyboard(interp); - - encoding = CFStringGetSystemEncoding(); - - for (i = 0; scriptMap[i].strKey != NULL; i++) { - if (scriptMap[i].numKey == encoding) { - encodingStr = scriptMap[i].strKey; - break; - } - } - if (encodingStr == NULL) { - encodingStr = "macRoman"; - } - - TkMacOSXCarbonEncoding = Tcl_GetEncoding (NULL, encodingStr); - if (TkMacOSXCarbonEncoding == NULL) { - TkMacOSXCarbonEncoding = Tcl_GetEncoding (NULL, NULL); - } + tkMacOSXInitialized = 1; /* - * When Tk is in a framework, force tcl_findLibrary to look in the + * When Tk is in a framework, force tcl_findLibrary to look in the * framework scripts directory. * FIXME: Should we come up with a more generic way of doing this? */ #ifdef TK_FRAMEWORK if (Tcl_MacOSXOpenVersionedBundleResources(interp, - "com.tcltk.tklibrary", TK_FRAMEWORK_VERSION, 1, PATH_MAX, tkLibPath) != TCL_OK) + "com.tcltk.tklibrary", TK_FRAMEWORK_VERSION, 1, PATH_MAX, + tkLibPath) != TCL_OK) #endif { /* Tk.framework not found, check if resource file is open */ @@ -181,12 +162,13 @@ TkpInit(interp) char fileName[L_tmpnam + 15]; uint32_t i, n; - /* Get resource data from __tk_rsrc section of tk library file */ + /* Get resource data from __tk_rsrc section of tk dylib file*/ n = _dyld_image_count(); for (i = 0; i < n; i++) { image = _dyld_get_image_header(i); if (image) { - data = getsectdatafromheader(image, SEG_TEXT, "__tk_rsrc", &size); + data = getsectdatafromheader(image, SEG_TEXT, + "__tk_rsrc", (void*)&size); if (data) { data += _dyld_get_image_vmaddr_slide(i); break; @@ -194,26 +176,32 @@ TkpInit(interp) } } while (data) { - OSStatus err; FSRef ref; SInt16 refNum; - /* Write resource data to temporary file and open it */ + /* + * Write resource data to temporary file and open it. + */ + strcpy(fileName, P_tmpdir); if (fileName[strlen(fileName) - 1] != '/') { strcat(fileName, "/"); } strcat(fileName, "tkMacOSX_XXXXXX"); fd = mkstemp(fileName); - if (fd == -1) break; + if (fd == -1) { + break; + } fcntl(fd, F_SETFD, FD_CLOEXEC); - if (write(fd, data, size) == -1) break; - err = FSPathMakeRef((unsigned char*)fileName, &ref, NULL); - if (err != noErr) break; - err = FSOpenResourceFile(&ref, 0, NULL, fsRdPerm, &refNum); -#ifdef TK_MAC_DEBUG - if (err != noErr) fprintf(stderr,"FSOpenResourceFile error %ld\n",err); -#endif + if (write(fd, data, size) == -1) { + break; + } + if(ChkErr(FSPathMakeRef, (unsigned char*)fileName, &ref, + NULL) != noErr) { + break; + } + ChkErr(FSOpenResourceFile, &ref, 0, NULL, fsRdPerm, + &refNum); break; } if (fd != -1) { @@ -224,13 +212,108 @@ TkpInit(interp) } } - /* REMOVE ME: Close stdin & stdout for remote debugging otherwise we - * will fight with gdb for stdin & stdout + /* + * If we are loaded into an executable that is not a bundled + * application, the window server does not let us come to the + * foreground. For such an executable, notify the window server that + * we are now a full GUI application. */ - if (getenv ("XCNOSTDIN") != NULL) { - close (0); - close (1); + /* Check whether we are a bundled executable: */ + bundleRef = CFBundleGetMainBundle(); + if (bundleRef) { + bundleUrl = CFBundleCopyBundleURL(bundleRef); + } + if (bundleUrl) { + /* + * A bundled executable is two levels down from its main bundle + * directory (e.g. Wish.app/Contents/MacOS/Wish), whereas an + * unbundled executable's main bundle directory is just the + * directory containing the executable. So to check whether we are + * bundled, we delete the last three path components of the + * executable's url and compare the resulting url with the main + * bundle url. + */ + int j = 3; + CFURLRef url = CFBundleCopyExecutableURL(bundleRef); + while (url && j--) { + CFURLRef parent = CFURLCreateCopyDeletingLastPathComponent(NULL, + url); + CFRelease(url); + url = parent; + } + if (url) { + bundledExecutable = CFEqual(bundleUrl, url); + CFRelease(url); + } + CFRelease(bundleUrl); + } + + /* If we are not a bundled executable, notify the window server that + * we are a foregroundable app. */ + if (!bundledExecutable) { + OSStatus err = procNotFound; + ProcessSerialNumber psn = { 0, kCurrentProcess }; + +#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 + if (1 +#if MAC_OS_X_VERSION_MIN_REQUIRED < 1030 + && TransformProcessType != NULL +#endif + ) { + err = ChkErr(TransformProcessType, &psn, + kProcessTransformToForegroundApplication); + } +#endif +#if MAC_OSX_TK_USE_CPS_SPI + if (err != noErr) { + /* + * When building or running on 10.2 or when the above fails, + * attempt to use undocumented CPS SPI to notify the window + * server. Load the SPI symbol dynamically, so that we don't + * break if it ever disappears or changes its name. + */ + TkMacOSXInitNamedSymbol(CoreGraphics, OSStatus, + CPSEnableForegroundOperation, ProcessSerialNumberPtr); + if (CPSEnableForegroundOperation) { + ChkErr(CPSEnableForegroundOperation, &psn); + } + } +#endif /* MAC_OSX_TK_USE_CPS_SPI */ + } + + TkMacOSXInitAppleEvents(interp); + TkMacOSXInitCarbonEvents(interp); + TkMacOSXInitMenus(interp); + TkMacOSXUseAntialiasedText(interp, -1); + TkMacOSXInitCGDrawing(interp, TRUE, 0); + TkMacOSXInitKeyboard(interp); + + encoding = CFStringGetSystemEncoding(); + + for (i = 0; scriptMap[i].strKey != NULL; i++) { + if (scriptMap[i].numKey == encoding) { + encodingStr = scriptMap[i].strKey; + break; + } + } + if (encodingStr == NULL) { + encodingStr = "macRoman"; + } + + TkMacOSXCarbonEncoding = Tcl_GetEncoding(NULL, encodingStr); + if (TkMacOSXCarbonEncoding == NULL) { + TkMacOSXCarbonEncoding = Tcl_GetEncoding(NULL, NULL); + } + + /* + * REMOVE ME: Close stdin & stdout for remote debugging otherwise we + * will fight with gdb for stdin & stdout + */ + + if (getenv("XCNOSTDIN") != NULL) { + close(0); + close(1); } /* @@ -241,18 +324,22 @@ TkpInit(interp) if (!isatty(0)) { struct stat st; + if (fstat(0, &st) || (S_ISCHR(st.st_mode) && st.st_blocks == 0)) { Tk_InitConsoleChannels(interp); Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDIN)); Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDOUT)); Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDERR)); + /* * Only show the console if we don't have a startup script * and tcl_interactive hasn't been set already. */ + if (Tcl_GetStartupScript(NULL) == NULL) { - CONST char *intvar = - Tcl_GetVar(interp, "tcl_interactive", TCL_GLOBAL_ONLY); + const char *intvar = Tcl_GetVar(interp, + "tcl_interactive", TCL_GLOBAL_ONLY); + if (intvar == NULL) { Tcl_SetVar(interp, "tcl_interactive", "1", TCL_GLOBAL_ONLY); @@ -263,73 +350,6 @@ TkpInit(interp) } } } - - /* - * If we are loaded into an executable that is not a bundled - * application, the window server does not let us come to the - * foreground. For such an executable, notify the window server that - * we are now a full GUI application. - */ - { - /* Check whether we are a bundled executable: */ - int bundledExecutable = 0; - CFBundleRef bundleRef = CFBundleGetMainBundle(); - CFURLRef bundleUrl = NULL; - if (bundleRef) { - bundleUrl = CFBundleCopyBundleURL(bundleRef); - } - if (bundleUrl) { - /* - * A bundled executable is two levels down from its main bundle - * directory (e.g. Wish.app/Contents/MacOS/Wish), whereas - * an unbundled executable's main bundle directory is just - * the directory containing the executable. - * So to check whether we are bundled, we delete the last three - * path components of the executable's url and compare the - * resulting url with the main bundle url. - */ - int j = 3; - CFURLRef url = CFBundleCopyExecutableURL(bundleRef); - while (url && j--) { - CFURLRef parent = CFURLCreateCopyDeletingLastPathComponent(NULL, url); - CFRelease(url); - url = parent; - } - if (url) { - bundledExecutable = CFEqual(bundleUrl, url); - CFRelease(url); - } - CFRelease(bundleUrl); - } - - /* If we are not a bundled executable, notify the window server that - * we are a foregroundable app. */ - if (!bundledExecutable) { - OSStatus err = procNotFound; - ProcessSerialNumber psn = { 0, kCurrentProcess }; -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 - if (TransformProcessType != NULL) { - err = TransformProcessType(&psn, - kProcessTransformToForegroundApplication); - } -#endif -#if MAC_OSX_TK_USE_CPS_SPI - if (err != noErr) { - /* - * When building or running on 10.2 or when the above fails, - * attempt to use undocumented CPS SPI to notify the window - * server. Load the SPI symbol dynamically, so that we don't - * break if it ever disappears or changes its name. - */ - TkMacOSXInitNamedSymbol(CoreGraphics, OSErr, - CPSEnableForegroundOperation, ProcessSerialNumberPtr); - if (CPSEnableForegroundOperation) { - CPSEnableForegroundOperation(&psn); - } - } -#endif /* MAC_OSX_TK_USE_CPS_SPI */ - } - } } if (tkLibPath[0] != '\0') { @@ -341,7 +361,7 @@ TkpInit(interp) TCL_GLOBAL_ONLY|TCL_LIST_ELEMENT|TCL_APPEND_VALUE); } - return Tcl_Eval(interp, initScript); + return Tcl_EvalEx(interp, initScript, -1, TCL_EVAL_GLOBAL); } /* @@ -349,25 +369,25 @@ TkpInit(interp) * * TkpGetAppName -- * - * Retrieves the name of the current application from a platform - * specific location. For Unix, the application name is the tail - * of the path contained in the tcl variable argv0. + * Retrieves the name of the current application from a platform + * specific location. For Unix, the application name is the tail + * of the path contained in the tcl variable argv0. * * Results: - * Returns the application name in the given Tcl_DString. + * Returns the application name in the given Tcl_DString. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ void -TkpGetAppName(interp, namePtr) - Tcl_Interp *interp; - Tcl_DString *namePtr; /* A previously initialized Tcl_DString. */ +TkpGetAppName( + Tcl_Interp *interp, + Tcl_DString *namePtr) /* A previously initialized Tcl_DString. */ { - CONST char *p, *name; + const char *p, *name; name = Tcl_GetVar(interp, "argv0", TCL_GLOBAL_ONLY); if ((name == NULL) || (*name == 0)) { @@ -386,22 +406,22 @@ TkpGetAppName(interp, namePtr) * * TkpDisplayWarning -- * - * This routines is called from Tk_Main to display warning - * messages that occur during startup. + * This routines is called from Tk_Main to display warning + * messages that occur during startup. * * Results: - * None. + * None. * * Side effects: - * Generates messages on stdout. + * Generates messages on stdout. * *---------------------------------------------------------------------- */ void -TkpDisplayWarning(msg, title) - CONST char *msg; /* Message to be displayed. */ - CONST char *title; /* Title of warning. */ +TkpDisplayWarning( + CONST char *msg, /* Message to be displayed. */ + CONST char *title) /* Title of warning. */ { Tcl_Channel errChannel = Tcl_GetStdChannel(TCL_STDERR); if (errChannel) { @@ -418,18 +438,18 @@ TkpDisplayWarning(msg, title) * TkMacOSXDefaultStartupScript -- * * - * On MacOS X, we look for a file in the Resources/Scripts - * directory called AppMain.tcl and if found, we set argv[1] to - * that, so that the rest of the code will find it, and add the - * Scripts folder to the auto_path. If we don't find the startup - * script, we just bag it, assuming the user is starting up some - * other way. + * On MacOS X, we look for a file in the Resources/Scripts + * directory called AppMain.tcl and if found, we set argv[1] to + * that, so that the rest of the code will find it, and add the + * Scripts folder to the auto_path. If we don't find the startup + * script, we just bag it, assuming the user is starting up some + * other way. * * Results: - * None. + * None. * * Side effects: - * Tcl_SetStartupScript() called when AppMain.tcl found. + * Tcl_SetStartupScript() called when AppMain.tcl found. * *---------------------------------------------------------------------- */ @@ -443,9 +463,9 @@ TkMacOSXDefaultStartupScript(void) if (bundleRef != NULL) { CFURLRef appMainURL; - appMainURL = CFBundleCopyResourceURL(bundleRef, - CFSTR("AppMain"), - CFSTR("tcl"), + appMainURL = CFBundleCopyResourceURL(bundleRef, + CFSTR("AppMain"), + CFSTR("tcl"), CFSTR("Scripts")); if (appMainURL != NULL) { @@ -458,7 +478,7 @@ TkMacOSXDefaultStartupScript(void) scriptFldrURL = CFURLCreateCopyDeletingLastPathComponent( NULL, appMainURL); if (scriptFldrURL != NULL) { - CFURLGetFileSystemRepresentation(scriptFldrURL, + CFURLGetFileSystemRepresentation(scriptFldrURL, true, (unsigned char*) scriptPath, PATH_MAX); CFRelease(scriptFldrURL); } @@ -474,23 +494,25 @@ TkMacOSXDefaultStartupScript(void) * TkMacOSXGetNamedSymbol -- * * - * Dynamically acquire address of a named symbol from a loaded - * dynamic library, so that we can use API that may not be - * available on all OS versions. - * If module is non-NULL and not the empty string, use twolevel - * namespace lookup. - * + * Dynamically acquire address of a named symbol from a loaded + * dynamic library, so that we can use API that may not be + * available on all OS versions. + * If module is non-NULL and not the empty string, use twolevel + * namespace lookup. + * * Results: - * Address of given symbol or NULL if unavailable. + * Address of given symbol or NULL if unavailable. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ MODULE_SCOPE void* -TkMacOSXGetNamedSymbol(const char* module, const char* symbol) +TkMacOSXGetNamedSymbol( + const char* module, + const char* symbol) { NSSymbol nsSymbol = NULL; if (module && *module) { @@ -502,7 +524,7 @@ TkMacOSXGetNamedSymbol(const char* module, const char* symbol) nsSymbol = NSLookupAndBindSymbol(symbol); } } - if(nsSymbol) { + if (nsSymbol) { return NSAddressOfSymbol(nsSymbol); } else { return NULL; diff --git a/macosx/tkMacOSXInt.h b/macosx/tkMacOSXInt.h index 9ff9069..06f73bc 100644 --- a/macosx/tkMacOSXInt.h +++ b/macosx/tkMacOSXInt.h @@ -5,11 +5,12 @@ * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2005-2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXInt.h,v 1.22 2007/04/21 19:06:38 hobbs Exp $ + * RCS: @(#) $Id: tkMacOSXInt.h,v 1.23 2007/04/23 21:24:33 das Exp $ */ #ifndef _TKMACINT @@ -23,6 +24,66 @@ #include #undef TextStyle +/* Define constants only available on Mac OS X 10.3 or later */ +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 + #define kEventAppAvailableWindowBoundsChanged 110 + #define kEventParamTransactionID 'trns' + #define kEventParamWindowPartCode 'wpar' + #define typeWindowPartCode 'wpar' + #define kMenuAttrDoNotUseUserCommandKeys (1 << 7) + #define kSimpleWindowClass 18 + #define kWindowDoesNotCycleAttribute (1L << 15) + #define kWindowAsyncDragAttribute (1L << 23) + #define kThemeBrushAlternatePrimaryHighlightColor -5 + #define kThemeResizeUpCursor 19 + #define kThemeResizeDownCursor 19 + #define kThemeResizeUpDownCursor 19 + #define kThemePoofCursor 19 + #define kThemeBackgroundMetal 6 + #define kThemeIncDecButtonSmall 21 + #define kThemeIncDecButtonMini 22 + #define kAppearancePartUpButton 20 + #define kAppearancePartDownButton 21 + #define kAppearancePartPageUpArea 22 + #define kAppearancePartPageDownArea 23 + #define kAppearancePartIndicator 129 + #define FixedToInt(a) ((short)(((Fixed)(a) + fixed1/2) >> 16)) + #define IntToFixed(a) ((Fixed)(a) << 16) +#endif +/* Define constants only available on Mac OS X 10.4 or later */ +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1040 + #define kWindowNoTitleBarAttribute (1L << 9) + #define kWindowMetalNoContentSeparatorAttribute (1L << 11) + #define kThemeDisclosureTriangle 6 + #define kThemeBrushListViewOddRowBackground 56 + #define kThemeBrushListViewEvenRowBackground 57 + #define kThemeBrushListViewColumnDivider 58 + #define kThemeMetricScrollBarMinThumbHeight 132 + #define kThemeMetricSmallScrollBarMinThumbHeight 134 + #define kThemeScrollBarMedium kThemeMediumScrollBar + #define kThemeScrollBarSmall kThemeSmallScrollBar + #ifdef __BIG_ENDIAN__ + #define kCGBitmapByteOrder32Host (4 << 12) + #else + #define kCGBitmapByteOrder32Host (2 << 12) + #endif + #endif +/* Define constants only available on Mac OS X 10.5 or later */ +#if MAC_OS_X_VERSION_MAX_ALLOWED < 1050 + #define kWindowUnifiedTitleAndToolbarAttribute (1L << 7) + #define kWindowTexturedSquareCornersAttribute (1L << 10) +#endif +/* Runtime HIToolbox version checking */ +#ifndef kHIToolboxVersionNumber10_3 + #define kHIToolboxVersionNumber10_3 (145) +#endif +#ifndef kHIToolboxVersionNumber10_4 + #define kHIToolboxVersionNumber10_4 (219) +#endif +#ifndef kHIToolboxVersionNumber10_5 + #define kHIToolboxVersionNumber10_5 (291) +#endif + /* * Include platform specific public interfaces. */ @@ -32,17 +93,19 @@ #endif struct TkWindowPrivate { - TkWindow *winPtr; /* Ptr to tk window or NULL if Pixmap */ - CGrafPtr grafPtr; + TkWindow *winPtr; /* Ptr to tk window or NULL if Pixmap */ + CGrafPtr grafPtr; + CGContextRef context; ControlRef rootControl; - int xOff; /* X offset from toplevel window */ - int yOff; /* Y offset from toplevel window */ + int xOff; /* X offset from toplevel window */ + int yOff; /* Y offset from toplevel window */ RgnHandle clipRgn; /* Visible region of window */ RgnHandle aboveClipRgn; /* Visible region of window & it's children */ + RgnHandle drawRgn; /* Clipped drawing region */ int referenceCount; /* Don't delete toplevel until children are * gone. */ - struct TkWindowPrivate *toplevel; /* Pointer to the toplevel - * datastruct. */ + struct TkWindowPrivate *toplevel; + /* Pointer to the toplevel datastruct. */ int flags; /* Various state see defines below. */ }; typedef struct TkWindowPrivate MacDrawable; @@ -54,50 +117,65 @@ typedef struct TkWindowPrivate MacDrawable; */ typedef struct TkMacOSXWindowList { - struct TkMacOSXWindowList *nextPtr; /* The next window in the list. */ - TkWindow *winPtr; /* This window */ + struct TkMacOSXWindowList *nextPtr; + /* The next window in the list. */ + TkWindow *winPtr; /* This window */ } TkMacOSXWindowList; /* * Defines use for the flags field of the MacDrawable data structure. */ - -#define TK_SCROLLBAR_GROW 1 -#define TK_CLIP_INVALID 2 -#define TK_HOST_EXISTS 4 -#define TK_DRAWN_UNDER_MENU 8 + +#define TK_SCROLLBAR_GROW 0x01 +#define TK_CLIP_INVALID 0x02 +#define TK_HOST_EXISTS 0x04 +#define TK_DRAWN_UNDER_MENU 0x08 +#define TK_CLIPPED_DRAW 0x10 /* * I am reserving TK_EMBEDDED = 0x100 in the MacDrawable flags * This is defined in tk.h. We need to duplicate the TK_EMBEDDED flag in the - * TkWindow structure for the window, but in the MacWin. This way we can + * TkWindow structure for the window, but in the MacWin. This way we can * still tell what the correct port is after the TKWindow structure has been - * freed. This actually happens when you bind destroy of a toplevel to + * freed. This actually happens when you bind destroy of a toplevel to * Destroy of a child. */ /* * This structure is for handling Netscape-type in process - * embedding where Tk does not control the top-level. It contains + * embedding where Tk does not control the top-level. It contains * various functions that are needed by Mac specific routines, like - * TkMacOSXGetDrawablePort. The definitions of the function types + * TkMacOSXGetDrawablePort. The definitions of the function types * are in tkMacOSX.h. */ typedef struct { - Tk_MacOSXEmbedRegisterWinProc *registerWinProc; - Tk_MacOSXEmbedGetGrafPortProc *getPortProc; - Tk_MacOSXEmbedMakeContainerExistProc *containerExistProc; - Tk_MacOSXEmbedGetClipProc *getClipProc; - Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc; + Tk_MacOSXEmbedRegisterWinProc *registerWinProc; + Tk_MacOSXEmbedGetGrafPortProc *getPortProc; + Tk_MacOSXEmbedMakeContainerExistProc *containerExistProc; + Tk_MacOSXEmbedGetClipProc *getClipProc; + Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc; } TkMacOSXEmbedHandler; MODULE_SCOPE TkMacOSXEmbedHandler *tkMacOSXEmbedHandler; /* + * Structure encapsulating current drawing environment. + */ + +typedef struct TkMacOSXDrawingContext { + CGContextRef context; + CGrafPtr port, savePort; + ThemeDrawingState saveState; + PixPatHandle penPat; + Rect portBounds; + Boolean portChanged; +} TkMacOSXDrawingContext; + +/* * Defines used for TkMacOSXInvalidateWindow */ - + #define TK_WINDOW_ONLY 0 #define TK_PARENT_WINDOW 1 @@ -120,14 +198,57 @@ MODULE_SCOPE TkMacOSXEmbedHandler *tkMacOSXEmbedHandler; * Defines for tkTextDisp.c */ -#define TK_LAYOUT_WITH_BASE_CHUNKS 1 -#define TK_DRAW_IN_CONTEXT 1 +#define TK_LAYOUT_WITH_BASE_CHUNKS 1 +#define TK_DRAW_IN_CONTEXT 1 + +#if !TK_DRAW_IN_CONTEXT +MODULE_SCOPE int TkMacOSXCompareColors(unsigned long c1, unsigned long c2); +#endif + +/* + * Macros abstracting checks only active in a debug build. + */ + +#ifdef TK_MAC_DEBUG +/* + * Macro to do debug message output. + */ +#define TkMacOSXDbgMsg(m, ...) do { \ + fprintf(stderr, "%s:%d: %s(): " m "\n", strrchr(__FILE__, '/')+1, \ + __LINE__, __func__, ##__VA_ARGS__); \ + } while (0) +/* + * Macro to do very common check for noErr return from given API and output + * debug message in case of failure. + */ +#define ChkErr(f, ...) ({ \ + OSStatus err = f(__VA_ARGS__); \ + if (err != noErr) { \ + TkMacOSXDbgMsg("%s failed: %ld", #f, err); \ + } \ + err;}) +/* + * Macro to check emptyness of shared temp regions before use in debug builds. + */ +#define TkMacOSXCheckTmpRgnEmpty(r) do { \ + if (!EmptyRgn(tkMacOSXtmpRgn##r)) { \ + Tcl_Panic("tkMacOSXtmpRgn%s nonempty", #r); \ + } \ + } while(0) +#else /* TK_MAC_DEBUG */ +#define TkMacOSXDbgMsg(m, ...) +#define ChkErr(f, ...) ({f(__VA_ARGS__);}) +#define TkMacOSXCheckTmpRgnEmpty(r) +#endif /* TK_MAC_DEBUG */ /* * Variables shared among various Mac Tk modules but are not * exported to the outside world. */ +MODULE_SCOPE RgnHandle tkMacOSXtmpRgn1; +MODULE_SCOPE RgnHandle tkMacOSXtmpRgn2; + /* * Globals shared among Macintosh Tk */ @@ -136,13 +257,6 @@ MODULE_SCOPE MenuHandle tkCurrentAppleMenu; /* Handle to current Apple Menu */ MODULE_SCOPE MenuHandle tkAppleMenu; /* Handle to default Apple Menu */ MODULE_SCOPE MenuHandle tkFileMenu; /* Handles to menus */ MODULE_SCOPE MenuHandle tkEditMenu; /* Handles to menus */ -MODULE_SCOPE RgnHandle tkMenuCascadeRgn;/* A region to clip with. */ -MODULE_SCOPE int tkUseMenuCascadeRgn; /* If this is 1, clipping code - * should intersect tkMenuCascadeRgn - * before drawing occurs. - * tkMenuCascadeRgn will only - * be valid when the value of this - * variable is 1. */ MODULE_SCOPE int tkPictureIsOpen; /* If this is 1, we are drawing to a * picture The clipping should then be * done relative to the bounds of the @@ -154,31 +268,72 @@ MODULE_SCOPE int tkPictureIsOpen; /* If this is 1, we are drawing to a * for CopyBits should also have * top,left values of 0,0 */ -MODULE_SCOPE TkMacOSXWindowList *tkMacOSXWindowListPtr; - /* The list of toplevels */ - +MODULE_SCOPE TkMacOSXWindowList *tkMacOSXWindowListPtr; /* List of toplevels */ MODULE_SCOPE Tcl_Encoding TkMacOSXCarbonEncoding; +/* + * Prototypes of internal procs not in the stubs table. + */ + +#if 0 +MODULE_SCOPE int XSetClipRectangles(Display *d, GC gc, int clip_x_origin, + int clip_y_origin, XRectangle* rectangles, int n, int ordering); +#endif +MODULE_SCOPE void TkpClipDrawableToRect(Display *display, Drawable d, int x, + int y, int width, int height); MODULE_SCOPE void TkMacOSXDisplayChanged(Display *display); +MODULE_SCOPE void TkMacOSXInitScrollbarMetrics(void); MODULE_SCOPE int TkMacOSXUseAntialiasedText(Tcl_Interp *interp, int enable); MODULE_SCOPE void TkMacOSXInitCarbonEvents(Tcl_Interp *interp); -MODULE_SCOPE int TkMacOSXInitCGDrawing(Tcl_Interp *interp, int enable, int antiAlias); +MODULE_SCOPE int TkMacOSXInitCGDrawing(Tcl_Interp *interp, int enable, + int antiAlias); MODULE_SCOPE void TkMacOSXInitKeyboard(Tcl_Interp *interp); MODULE_SCOPE void TkMacOSXDefaultStartupScript(void); -MODULE_SCOPE int TkMacOSXGenerateFocusEvent( Window window, int activeFlag); +MODULE_SCOPE int TkMacOSXGenerateFocusEvent(Window window, int activeFlag); +MODULE_SCOPE int TkMacOSXGenerateParentMenuSelectEvent(MenuRef menu); +MODULE_SCOPE int TkMacOSXGenerateMenuSelectEvent(MenuRef menu, + MenuItemIndex index); +MODULE_SCOPE void TkMacOSXClearActiveMenu(MenuRef menu); MODULE_SCOPE WindowClass TkMacOSXWindowClass(TkWindow *winPtr); MODULE_SCOPE int TkMacOSXIsWindowZoomed(TkWindow *winPtr); MODULE_SCOPE int TkGenerateButtonEventForXPointer(Window window); -MODULE_SCOPE int TkMacOSXCompareColors(unsigned long c1, unsigned long c2); +MODULE_SCOPE EventModifiers TkMacOSXModifierState(void); +MODULE_SCOPE int TkMacOSXSetupDrawingContext(Drawable d, GC gc, int useCG, + TkMacOSXDrawingContext *dc); +MODULE_SCOPE void TkMacOSXRestoreDrawingContext(TkMacOSXDrawingContext *dc); +MODULE_SCOPE void TkMacOSXSetColorInPort(unsigned long pixel, int fg, + PixPatHandle penPat); +MODULE_SCOPE void TkMacOSXSetColorInContext(unsigned long pixel, + CGContextRef context); +MODULE_SCOPE int TkMacOSXRunTclEventLoop(void); +MODULE_SCOPE OSStatus TkMacOSXStartTclEventLoopCarbonTimer(void); +MODULE_SCOPE OSStatus TkMacOSXStopTclEventLoopCarbonTimer(void); +MODULE_SCOPE void TkMacOSXTrackingLoop(int tracking); +MODULE_SCOPE OSStatus TkMacOSXReceiveAndDispatchEvent(void); +MODULE_SCOPE void TkMacOSXInstallWindowCarbonEventHandler(Tcl_Interp *interp, + WindowRef window); +MODULE_SCOPE int TkMacOSXMakeFullscreen(TkWindow *winPtr, WindowRef window, + int fullscreen, Tcl_Interp *interp); +MODULE_SCOPE void TkMacOSXEnterExitFullscreen(TkWindow *winPtr, int active); + +MODULE_SCOPE void* TkMacOSXGetNamedSymbol(const char* module, + const char* symbol); + +/* + * Macro abstracting use of TkMacOSXGetNamedSymbol to init named symbols. + */ -MODULE_SCOPE void* TkMacOSXGetNamedSymbol(const char* module, const char* symbol); -/* Macro to abstract common use of TkMacOSXGetNamedSymbol to initialize named symbols */ #define TkMacOSXInitNamedSymbol(module, ret, symbol, ...) \ static ret (* symbol)(__VA_ARGS__) = (void*)(-1L); \ if (symbol == (void*)(-1L)) { \ - symbol = TkMacOSXGetNamedSymbol(STRINGIFY(module), STRINGIFY(_##symbol));\ + symbol = TkMacOSXGetNamedSymbol(STRINGIFY(module), \ + STRINGIFY(_##symbol)); \ } +/* + * Include the stubbed internal platform-specific API. + */ + #include "tkIntPlatDecls.h" #endif /* _TKMACINT */ diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c index 08d61a4..14bf641 100644 --- a/macosx/tkMacOSXKeyEvent.c +++ b/macosx/tkMacOSXKeyEvent.c @@ -1,190 +1,172 @@ /* * tkMacOSXKeyEvent.c -- * - * This file implements functions that decode & handle keyboard events - * on MacOS X. + * This file implements functions that decode & handle keyboard events + * on MacOS X. * * Copyright 2001, Apple Computer, Inc. - * Copyright (c) 2006 Daniel A. Steffen + * Copyright (c) 2006-2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * The following terms apply to all files originating from Apple - * Computer, Inc. ("Apple") and associated with the software - * unless explicitly disclaimed in individual files. - * - * - * Apple hereby grants permission to use, copy, modify, - * distribute, and license this software and its documentation - * for any purpose, provided that existing copyright notices are - * retained in all copies and that this notice is included - * verbatim in any distributions. No written agreement, license, - * or royalty fee is required for any of the authorized - * uses. Modifications to this software may be copyrighted by - * their authors and need not follow the licensing terms - * described here, provided that the new terms are clearly - * indicated on the first page of each file where they apply. - * - * - * IN NO EVENT SHALL APPLE, THE AUTHORS OR DISTRIBUTORS OF THE - * SOFTWARE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, - * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF - * THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, - * EVEN IF APPLE OR THE AUTHORS HAVE BEEN ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. APPLE, THE AUTHORS AND - * DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, - * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS - * SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND APPLE,THE - * AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE - * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. - * - * GOVERNMENT USE: If you are acquiring this software on behalf - * of the U.S. government, the Government shall have only - * "Restricted Rights" in the software and related documentation - * as defined in the Federal Acquisition Regulations (FARs) in - * Clause 52.227.19 (c) (2). If you are acquiring the software - * on behalf of the Department of Defense, the software shall be - * classified as "Commercial Computer Software" and the - * Government shall have only "Restricted Rights" as defined in - * Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the - * foregoing, the authors grant the U.S. Government and others - * acting in its behalf permission to use and distribute the - * software in accordance with the terms specified in this - * license. - * - * RCS: @(#) $Id: tkMacOSXKeyEvent.c,v 1.20 2007/04/21 19:06:38 hobbs Exp $ + * The following terms apply to all files originating from Apple + * Computer, Inc. ("Apple") and associated with the software + * unless explicitly disclaimed in individual files. + * + * + * Apple hereby grants permission to use, copy, modify, + * distribute, and license this software and its documentation + * for any purpose, provided that existing copyright notices are + * retained in all copies and that this notice is included + * verbatim in any distributions. No written agreement, license, + * or royalty fee is required for any of the authorized + * uses. Modifications to this software may be copyrighted by + * their authors and need not follow the licensing terms + * described here, provided that the new terms are clearly + * indicated on the first page of each file where they apply. + * + * + * IN NO EVENT SHALL APPLE, THE AUTHORS OR DISTRIBUTORS OF THE + * SOFTWARE BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, + * INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF + * THIS SOFTWARE, ITS DOCUMENTATION, OR ANY DERIVATIVES THEREOF, + * EVEN IF APPLE OR THE AUTHORS HAVE BEEN ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. APPLE, THE AUTHORS AND + * DISTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, + * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. THIS + * SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, AND APPLE,THE + * AUTHORS AND DISTRIBUTORS HAVE NO OBLIGATION TO PROVIDE + * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. + * + * GOVERNMENT USE: If you are acquiring this software on behalf + * of the U.S. government, the Government shall have only + * "Restricted Rights" in the software and related documentation + * as defined in the Federal Acquisition Regulations (FARs) in + * Clause 52.227.19 (c) (2). If you are acquiring the software + * on behalf of the Department of Defense, the software shall be + * classified as "Commercial Computer Software" and the + * Government shall have only "Restricted Rights" as defined in + * Clause 252.227-7013 (c) (1) of DFARs. Notwithstanding the + * foregoing, the authors grant the U.S. Government and others + * acting in its behalf permission to use and distribute the + * software in accordance with the terms specified in this + * license. + * + * RCS: @(#) $Id: tkMacOSXKeyEvent.c,v 1.21 2007/04/23 21:24:33 das Exp $ */ #include "tkMacOSXInt.h" #include "tkMacOSXEvent.h" /* -#ifdef TK_MAC_DEBUG +#ifdef TK_MAC_DEBUG #define TK_MAC_DEBUG_KEYBOARD #endif */ typedef struct { - WindowRef whichWindow; - int global_x, global_y; - int local_x, local_y; + WindowRef whichWindow; + int global_x, global_y; + int local_x, local_y; unsigned int state; + UInt32 keyCode; + UInt32 keyModifiers; + UInt32 message; unsigned char ch; - UInt32 keyCode; - UInt32 keyModifiers; - UInt32 message; } KeyEventData; -static Tk_Window gGrabWinPtr = NULL; /* Current grab window, - * NULL if no grab. */ -static Tk_Window gKeyboardWinPtr = NULL; /* Current keyboard grab window. */ - -static UInt32 deadKeyStateUp = 0; /* The deadkey state for the current - * sequence of keyup events or 0 if - * not in a deadkey sequence */ -static UInt32 deadKeyStateDown = 0; /* Ditto for keydown */ +static Tk_Window grabWinPtr = NULL; + /* Current grab window, NULL if no grab. */ +static Tk_Window keyboardGrabWinPtr = NULL; + /* Current keyboard grab window. */ +static UInt32 deadKeyStateUp = 0; + /* The deadkey state for the current sequence + * of keyup events or 0 if not in a deadkey + * sequence */ +static UInt32 deadKeyStateDown = 0; + /* Ditto for keydown */ /* * Declarations for functions used only in this file. */ - -static int InitKeyData( - KeyEventData * keyEventDataPtr); - -static int InitKeyEvent( - XEvent * eventPtr, - KeyEventData * e, - UInt32 savedKeyCode, - UInt32 savedModifiers); - -static int GenerateKeyEvent ( - UInt32 eKind, - KeyEventData * e, - UInt32 savedKeyCode, - UInt32 savedModifiers, - const UniChar * chars, int numChars); - -static int GetKeyboardLayout ( - Ptr * resourcePtr, TextEncoding * encodingPtr); -static TextEncoding GetKCHREncoding( - ScriptCode script, SInt32 layoutid); - -static int KeycodeToUnicodeViaUnicodeResource( - UniChar * uniChars, int maxChars, - Ptr uchr, - EventKind eKind, - UInt32 keycode, UInt32 modifiers, - UInt32 * deadKeyStatePtr); - -static int KeycodeToUnicodeViaKCHRResource( - UniChar * uniChars, int maxChars, - Ptr kchr, TextEncoding encoding, - EventKind eKind, - UInt32 keycode, UInt32 modifiers, - UInt32 * deadKeyStatePtr); + +static int InitKeyData(KeyEventData *keyEventDataPtr); +static int InitKeyEvent(XEvent *eventPtr, KeyEventData *e, UInt32 savedKeyCode, + UInt32 savedModifiers); +static int GenerateKeyEvent(UInt32 eKind, KeyEventData *e, UInt32 savedKeyCode, + UInt32 savedModifiers, const UniChar *chars, int numChars); +static int GetKeyboardLayout(Ptr *resourcePtr, TextEncoding *encodingPtr); +static TextEncoding GetKCHREncoding(ScriptCode script, SInt32 layoutid); +static int KeycodeToUnicodeViaUnicodeResource(UniChar *uniChars, int maxChars, + Ptr uchr, EventKind eKind, UInt32 keycode, UInt32 modifiers, + UInt32 *deadKeyStatePtr); +static int KeycodeToUnicodeViaKCHRResource(UniChar *uniChars, int maxChars, + Ptr kchr, TextEncoding encoding, EventKind eKind, UInt32 keycode, + UInt32 modifiers, UInt32 *deadKeyStatePtr); + /* *---------------------------------------------------------------------- * * TkMacOSXProcessKeyboardEvent -- * - * This routine processes the event in eventPtr, and - * generates the appropriate Tk events from it. + * This routine processes the event in eventPtr, and + * generates the appropriate Tk events from it. * * Results: - * True if event(s) are generated - false otherwise. + * True if event(s) are generated - false otherwise. * * Side effects: - * Additional events may be place on the Tk event queue. + * Additional events may be place on the Tk event queue. * *---------------------------------------------------------------------- */ MODULE_SCOPE int TkMacOSXProcessKeyboardEvent( - TkMacOSXEvent * eventPtr, - MacEventStatus * statusPtr) + TkMacOSXEvent *eventPtr, + MacEventStatus *statusPtr) { static UInt32 savedKeyCode = 0; static UInt32 savedModifiers = 0; static UniChar savedChar = 0; - OSStatus status; + OSStatus err; KeyEventData keyEventData; - MenuRef menuRef; + MenuRef menuRef; MenuItemIndex menuItemIndex; int eventGenerated; UniChar uniChars[5]; /* make this larger, if needed */ UInt32 uniCharsLen = 0; if (!InitKeyData(&keyEventData)) { - statusPtr->err = 1; - return false; + statusPtr->err = 1; + return false; } - + /* * Because of the way that Tk operates, we can't in general funnel menu - * accelerators through IsMenuKeyEvent. Tk treats accelerators as mere + * accelerators through IsMenuKeyEvent. Tk treats accelerators as mere * decoration, and the user has to install bindings to get them to fire. * * However, the only way to trigger the Hide & Hide Others functions - * is by invoking the Menu command for Hide. So there is no nice way to + * is by invoking the Menu command for Hide. So there is no nice way to * provide a Tk command to hide the app which would be available for a - * binding. So I am going to hijack Command-H and Command-Shift-H - * here, and run the menu commands. Since the HI Guidelines explicitly - * reserve these for Hide, this isn't such a bad thing. Also, if you do + * binding. So I am going to hijack Command-H and Command-Shift-H + * here, and run the menu commands. Since the HI Guidelines explicitly + * reserve these for Hide, this isn't such a bad thing. Also, if you do * rebind Command-H to another menu item, Hide will lose its binding. - * - * Note that I don't really do anything at this point, + * + * Note that I don't really do anything at this point, * I just mark stopProcessing as 0 and return, and then the * RecieveAndProcessEvent code will dispatch the event to the default * handler. */ - if ((eventPtr->eKind == kEventRawKeyDown + if ((eventPtr->eKind == kEventRawKeyDown || eventPtr->eKind == kEventRawKeyRepeat) - && IsMenuKeyEvent(tkCurrentAppleMenu, eventPtr->eventRef, + && IsMenuKeyEvent(tkCurrentAppleMenu, eventPtr->eventRef, kMenuEventQueryOnly, &menuRef, &menuItemIndex)) { MenuCommand menuCmd; @@ -203,114 +185,97 @@ TkMacOSXProcessKeyboardEvent( } } - status = GetEventParameter(eventPtr->eventRef, - kEventParamKeyMacCharCodes, - typeChar, NULL, - sizeof(keyEventData.ch), NULL, - &keyEventData.ch); - if (status != noErr) { -#ifdef TK_MAC_DEBUG - fprintf (stderr, "Failed to retrieve KeyMacCharCodes\n"); -#endif - statusPtr->err = 1; - return false; - } - status = GetEventParameter(eventPtr->eventRef, - kEventParamKeyCode, - typeUInt32, NULL, - sizeof(keyEventData.keyCode), NULL, - &keyEventData.keyCode); - if (status != noErr) { -#ifdef TK_MAC_DEBUG - fprintf (stderr, "Failed to retrieve KeyCode\n"); -#endif - statusPtr->err = 1; - return false; + err = ChkErr(GetEventParameter, eventPtr->eventRef, + kEventParamKeyMacCharCodes, typeChar, NULL, + sizeof(keyEventData.ch), NULL, &keyEventData.ch); + if (err != noErr) { + statusPtr->err = 1; + return false; } - status = GetEventParameter(eventPtr->eventRef, - kEventParamKeyModifiers, - typeUInt32, NULL, - sizeof(keyEventData.keyModifiers), NULL, - &keyEventData.keyModifiers); - if (status != noErr) { -#ifdef TK_MAC_DEBUG - fprintf (stderr, "Failed to retrieve KeyModifiers\n"); -#endif - statusPtr->err = 1; - return false; + err = ChkErr(GetEventParameter, eventPtr->eventRef, kEventParamKeyCode, + typeUInt32, NULL, sizeof(keyEventData.keyCode), NULL, + &keyEventData.keyCode); + if (err != noErr) { + statusPtr->err = 1; + return false; + } + err = ChkErr(GetEventParameter, eventPtr->eventRef, + kEventParamKeyModifiers, typeUInt32, NULL, + sizeof(keyEventData.keyModifiers), NULL, + &keyEventData.keyModifiers); + if (err != noErr) { + statusPtr->err = 1; + return false; } switch (eventPtr->eKind) { - case kEventRawKeyUp: - case kEventRawKeyDown: - case kEventRawKeyRepeat: - { - UInt32 *deadKeyStatePtr; - - if (kEventRawKeyDown == eventPtr->eKind) { - deadKeyStatePtr = &deadKeyStateDown; - } else { - deadKeyStatePtr = &deadKeyStateUp; - } - - uniCharsLen = TkMacOSXKeycodeToUnicode( - uniChars, sizeof(uniChars)/sizeof(*uniChars), - eventPtr->eKind, - keyEventData.keyCode, keyEventData.keyModifiers, - deadKeyStatePtr); - } + case kEventRawKeyUp: + case kEventRawKeyDown: + case kEventRawKeyRepeat: { + UInt32 *deadKeyStatePtr; + + if (kEventRawKeyDown == eventPtr->eKind) { + deadKeyStatePtr = &deadKeyStateDown; + } else { + deadKeyStatePtr = &deadKeyStateUp; + } + + uniCharsLen = TkMacOSXKeycodeToUnicode(uniChars, + sizeof(uniChars)/sizeof(*uniChars), eventPtr->eKind, + keyEventData.keyCode, keyEventData.keyModifiers, + deadKeyStatePtr); + break; + } } if (kEventRawKeyUp == eventPtr->eKind) { - /* - * For some reason the deadkey processing for KeyUp doesn't work - * sometimes, so we fudge and use the last detected KeyDown. - */ - - if((0 == uniCharsLen) && (0 != savedChar)) { - uniChars[0] = savedChar; - uniCharsLen = 1; - } - - /* - * Suppress keyup events while we have a deadkey sequence on keydown. - * We still *do* want to collect deadkey state in this situation if - * the system provides it, that's why we do this only after - * TkMacOSXKeycodeToUnicode(). - */ - - if (0 != deadKeyStateDown) { - uniCharsLen = 0; - } + /* + * For some reason the deadkey processing for KeyUp doesn't work + * sometimes, so we fudge and use the last detected KeyDown. + */ + + if ((0 == uniCharsLen) && (0 != savedChar)) { + uniChars[0] = savedChar; + uniCharsLen = 1; + } + + /* + * Suppress keyup events while we have a deadkey sequence on keydown. + * We still *do* want to collect deadkey state in this situation if + * the system provides it, that's why we do this only after + * TkMacOSXKeycodeToUnicode(). + */ + + if (0 != deadKeyStateDown) { + uniCharsLen = 0; + } } keyEventData.message = keyEventData.ch|(keyEventData.keyCode << 8); - eventGenerated = GenerateKeyEvent( - eventPtr->eKind, &keyEventData, - savedKeyCode, savedModifiers, - uniChars, uniCharsLen); + eventGenerated = GenerateKeyEvent(eventPtr->eKind, &keyEventData, + savedKeyCode, savedModifiers, uniChars, uniCharsLen); savedModifiers = keyEventData.keyModifiers; if ((kEventRawKeyDown == eventPtr->eKind) && (uniCharsLen > 0)) { - savedChar = uniChars[0]; + savedChar = uniChars[0]; } else { - savedChar = 0; + savedChar = 0; } - + statusPtr->stopProcessing = 1; if (eventGenerated == 0) { - savedKeyCode = keyEventData.message; - return false; + savedKeyCode = keyEventData.message; + return false; } else if (eventGenerated == -1) { - savedKeyCode = 0; - statusPtr->stopProcessing = 0; - return false; + savedKeyCode = 0; + statusPtr->stopProcessing = 0; + return false; } else { - savedKeyCode = 0; - return true; + savedKeyCode = 0; + return true; } } @@ -319,107 +284,101 @@ TkMacOSXProcessKeyboardEvent( * * GenerateKeyEvent -- * - * Given Macintosh keyUp, keyDown & autoKey events (in their "raw" - * form) and a list of unicode characters this function generates the - * appropriate X key events. + * Given Macintosh keyUp, keyDown & autoKey events (in their "raw" + * form) and a list of unicode characters this function generates the + * appropriate X key events. * - * Parameter eKind is a raw keyboard event. e contains the data sent - * with the event. savedKeyCode and savedModifiers contain the values - * from the last event that came before (see - * TkMacOSXProcessKeyboardEvent()). chars/numChars has the Unicode - * characters for which we want to create events. + * Parameter eKind is a raw keyboard event. e contains the data sent + * with the event. savedKeyCode and savedModifiers contain the values + * from the last event that came before (see + * TkMacOSXProcessKeyboardEvent()). chars/numChars has the Unicode + * characters for which we want to create events. * * Results: - * 1 if an event was generated, -1 for any error. + * 1 if an event was generated, -1 for any error. * * Side effects: - * Additional events may be place on the Tk event queue. + * Additional events may be place on the Tk event queue. * *---------------------------------------------------------------------- */ static int GenerateKeyEvent( - UInt32 eKind, - KeyEventData * e, - UInt32 savedKeyCode, - UInt32 savedModifiers, - const UniChar * chars, int numChars) + UInt32 eKind, + KeyEventData * e, + UInt32 savedKeyCode, + UInt32 savedModifiers, + const UniChar * chars, + int numChars) { XEvent event; int i; - + if (-1 == InitKeyEvent(&event, e, savedKeyCode, savedModifiers)) { - return -1; + return -1; } if (kEventRawKeyModifiersChanged == eKind) { + if (savedModifiers > e->keyModifiers) { + event.xany.type = KeyRelease; + } else { + event.xany.type = KeyPress; + } - if (savedModifiers > e->keyModifiers) { - event.xany.type = KeyRelease; - } else { - event.xany.type = KeyPress; - } - - /* - * Use special '-1' to signify a special keycode to our - * platform specific code in tkMacOSXKeyboard.c. This is - * rather like what happens on Windows. - */ - - event.xany.send_event = -1; - - /* - * Set keycode (which was zero) to the changed modifier - */ - - event.xkey.keycode = (e->keyModifiers ^ savedModifiers); - Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); + /* + * Use special '-1' to signify a special keycode to our + * platform specific code in tkMacOSXKeyboard.c. This is + * rather like what happens on Windows. + */ - } else { + event.xany.send_event = -1; - for (i = 0; i < numChars; ++i) { - - /* - * Encode one char in the trans_chars array that was already - * introduced for MS Windows. Don't encode the string, if it is - * a control character but was not generated with a real control - * modifier. Such control characters get generated by KeyTrans() - * for special keys, but we rather want to identify those by - * their KeySyms. - */ - - event.xkey.trans_chars[0] = 0; - if ((controlKey & e->keyModifiers) || (chars[i] >= ' ')) { - int done; - done = Tcl_UniCharToUtf(chars[i],event.xkey.trans_chars); - event.xkey.trans_chars[done] = 0; - } - - switch(eKind) { - case kEventRawKeyDown: - event.xany.type = KeyPress; - Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); - break; - case kEventRawKeyUp: - event.xany.type = KeyRelease; - Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); - break; - case kEventRawKeyRepeat: - event.xany.type = KeyRelease; - Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); - event.xany.type = KeyPress; - Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); - break; - default: -#ifdef TK_MAC_DEBUG - fprintf (stderr, - "GenerateKeyEvent(): Invalid parameter eKind %d\n", - (int) eKind); -#endif - return -1; - } - } + /* + * Set keycode (which was zero) to the changed modifier + */ + + event.xkey.keycode = (e->keyModifiers ^ savedModifiers); + Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); + + } else { + for (i = 0; i < numChars; ++i) { + /* + * Encode one char in the trans_chars array that was already + * introduced for MS Windows. Don't encode the string, if it is + * a control character but was not generated with a real control + * modifier. Such control characters get generated by KeyTrans() + * for special keys, but we rather want to identify those by + * their KeySyms. + */ + + event.xkey.trans_chars[0] = 0; + if ((controlKey & e->keyModifiers) || (chars[i] >= ' ')) { + int done; + done = Tcl_UniCharToUtf(chars[i],event.xkey.trans_chars); + event.xkey.trans_chars[done] = 0; + } + + switch(eKind) { + case kEventRawKeyDown: + event.xany.type = KeyPress; + Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); + break; + case kEventRawKeyUp: + event.xany.type = KeyRelease; + Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); + break; + case kEventRawKeyRepeat: + event.xany.type = KeyRelease; + Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); + event.xany.type = KeyPress; + Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); + break; + default: + TkMacOSXDbgMsg("Invalid parameter eKind %ld", eKind); + return -1; + } + } } return 1; @@ -430,33 +389,32 @@ GenerateKeyEvent( * * InitKeyData -- * - * This routine initializes a KeyEventData structure by asking the OS - * and Tk for all the global information needed here. + * This routine initializes a KeyEventData structure by asking the OS + * and Tk for all the global information needed here. * * Results: - * True if the current front window can be found in Tk data structures - * - false otherwise. + * True if the current front window can be found in Tk data structures + * - false otherwise. * * Side Effects: - * None + * None * *---------------------------------------------------------------------- */ -static int -InitKeyData(KeyEventData * keyEventDataPtr) + +static int +InitKeyData( + KeyEventData *keyEventDataPtr) { - memset (keyEventDataPtr, 0, sizeof(*keyEventDataPtr)); + memset(keyEventDataPtr, 0, sizeof(*keyEventDataPtr)); keyEventDataPtr->whichWindow = ActiveNonFloatingWindow(); if (keyEventDataPtr->whichWindow == NULL) { - return false; + return false; } - XQueryPointer(NULL, None, NULL, NULL, - &keyEventDataPtr->global_x, - &keyEventDataPtr->global_y, - &keyEventDataPtr->local_x, - &keyEventDataPtr->local_y, - &keyEventDataPtr->state); + XQueryPointer(NULL, None, NULL, NULL, &keyEventDataPtr->global_x, + &keyEventDataPtr->global_y, &keyEventDataPtr->local_x, + &keyEventDataPtr->local_y, &keyEventDataPtr->state); return true; } @@ -466,52 +424,52 @@ InitKeyData(KeyEventData * keyEventDataPtr) * * InitKeyEvent -- * - * Initialize an XEvent structure by asking Tk for global information. - * Also uses a KeyEventData structure and other current state. + * Initialize an XEvent structure by asking Tk for global information. + * Also uses a KeyEventData structure and other current state. * * Results: - * 1 on success, -1 for any error. + * 1 on success, -1 for any error. * * Side effects: - * Additional events may be place on the Tk event queue. + * Additional events may be place on the Tk event queue. * *---------------------------------------------------------------------- */ -/* - * We have a general problem here. How do we handle 'Option-char' - * keypresses? The problem is that we might want to bind to some of these - * (e.g. Cmd-Opt-d is 'uncomment' in Alpha). OTOH Option-d actually produces +/* + * We have a general problem here. How do we handle 'Option-char' + * keypresses? The problem is that we might want to bind to some of these + * (e.g. Cmd-Opt-d is 'uncomment' in Alpha). OTOH Option-d actually produces * a real character on MacOS, namely a mathematical delta. * * The current behaviour is that a binding goes by the combinations of - * modifiers and base keysym, that is Option-d. The string value of the + * modifiers and base keysym, that is Option-d. The string value of the * event is the mathematical delta character, so if no binding calls * [break], the text widget will insert that character. * - * Note that this is similar to control combinations on all platforms. They + * Note that this is similar to control combinations on all platforms. They * also generate events that have the base character as keysym and a real - * control character as character value. So Ctrl+C gets us the keysym XK_C, + * control character as character value. So Ctrl+C gets us the keysym XK_C, * the modifier Control (so you can bind ) and a string value as * "\u0003". - * + * * For a different solutions we may want for the event to contain keysyms for - * *both* the 'Opt-d' side of things and the mathematical delta. Then a + * *both* the 'Opt-d' side of things and the mathematical delta. Then a * binding on Opt-d will trigger, but a binding on mathematical delta would - * also trigger. This would require changes in the core, though. + * also trigger. This would require changes in the core, though. */ static int InitKeyEvent( - XEvent * eventPtr, - KeyEventData * e, - UInt32 savedKeyCode, - UInt32 savedModifiers) + XEvent * eventPtr, + KeyEventData * e, + UInt32 savedKeyCode, + UInt32 savedModifiers) { Window window; Tk_Window tkwin; TkDisplay *dispPtr; - + /* * The focus must be in the FrontWindow on the Macintosh. * We then query Tk to determine the exact Tk window @@ -521,20 +479,16 @@ InitKeyEvent( window = TkMacOSXGetXWindow(e->whichWindow); dispPtr = TkGetDisplayList(); tkwin = Tk_IdToWindow(dispPtr->display, window); - - if (tkwin == NULL) { -#ifdef TK_MAC_DEBUG - fprintf(stderr,"tkwin == NULL, %d\n", __LINE__); -#endif - return -1; + + if (!tkwin) { + TkMacOSXDbgMsg("tkwin == NULL"); + return -1; } - + tkwin = (Tk_Window) ((TkWindow *) tkwin)->dispPtr->focusPtr; - if (tkwin == NULL) { -#ifdef TK_MAC_DEBUG - fprintf(stderr,"tkwin == NULL, %d\n", __LINE__); -#endif - return -1; + if (!tkwin) { + TkMacOSXDbgMsg("tkwin == NULL"); + return -1; } eventPtr->xany.send_event = false; @@ -551,302 +505,223 @@ InitKeyEvent( eventPtr->xkey.state = e->state; eventPtr->xkey.trans_chars[0] = 0; - Tk_TopCoordsToWindow( - tkwin, e->local_x, e->local_y, - &eventPtr->xkey.x, &eventPtr->xkey.y); + Tk_TopCoordsToWindow(tkwin, e->local_x, e->local_y, &eventPtr->xkey.x, + &eventPtr->xkey.y); - eventPtr->xkey.keycode = e->ch | - ((savedKeyCode & charCodeMask) << 8) | - ((e->message&keyCodeMask) << 8); + eventPtr->xkey.keycode = e->ch | ((savedKeyCode & charCodeMask) << 8) | + ((e->message&keyCodeMask) << 8); return 1; } - /* - * If we have old headers, we need to define these types and constants - * ourself. We use preprocessor macros instead of enums and typedefs, - * because macros work even in case of version misunderstandings, while - * duplicate enums and typedefs would give errrors. - */ - -#if MAC_OS_X_VERSION_MAX_ALLOWED < 1020 -#define KeyboardLayoutRef Ptr -#define KeyboardLayoutPropertyTag UInt32 -#define kKLKCHRData 0 -#define kKLuchrData 1 -#define kKLIdentifier 2 -#endif - -/* *---------------------------------------------------------------------- * * GetKeyboardLayout -- * - * Queries the OS for a pointer to a keyboard resource. + * Queries the OS for a pointer to a keyboard resource. * - * This function works with the keyboard layout switch menu. It uses - * Keyboard Layout Services, where available. + * This function works with the keyboard layout switch menu. It uses + * Keyboard Layout Services, where available. * * Results: - * 1 if there is returned a Unicode 'uchr' resource in *resourcePtr, 0 - * if it is a classic 'KCHR' resource. A pointer to the actual resource - * data goes into *resourcePtr. If the resource is a 'KCHR' resource, - * the corresponding Mac encoding goes into *encodingPtr. + * 1 if there is returned a Unicode 'uchr' resource in *resourcePtr, 0 + * if it is a classic 'KCHR' resource. A pointer to the actual resource + * data goes into *resourcePtr. If the resource is a 'KCHR' resource, + * the corresponding Mac encoding goes into *encodingPtr. * * Side effects: - * Sets some internal static variables. + * Sets some internal static variables. * *---------------------------------------------------------------------- */ static int -GetKeyboardLayout (Ptr * resourcePtr, TextEncoding * encodingPtr) +GetKeyboardLayout( + Ptr *resourcePtr, + TextEncoding *encodingPtr) { static KeyboardLayoutRef lastLayout = NULL; static SInt32 lastLayoutId; static TextEncoding lastEncoding = kTextEncodingMacRoman; static Ptr uchr = NULL; static Ptr KCHR = NULL; - static Handle handle = NULL; - int hasLayoutChanged = false; KeyboardLayoutRef currentLayout = NULL; SInt32 currentLayoutId = 0; ScriptCode currentKeyScript; - /* - * Several code branches need this information. - */ - currentKeyScript = GetScriptManagerVariable(smKeyScript); - TkMacOSXInitNamedSymbol(HIToolbox, OSStatus, KLGetCurrentKeyboardLayout, - KeyboardLayoutRef*); - TkMacOSXInitNamedSymbol(HIToolbox, OSStatus, KLGetKeyboardLayoutProperty, - KeyboardLayoutRef, KeyboardLayoutPropertyTag, const void**); - if (KLGetCurrentKeyboardLayout && KLGetKeyboardLayoutProperty) { - - /* - * Use the Keyboard Layout Services (these functions only exist since - * 10.2). - */ - - KLGetCurrentKeyboardLayout(¤tLayout); - - if (currentLayout != NULL) { - - /* - * The layout pointer could in theory be the same for different - * layouts, only the id gives us the information that the - * keyboard has actually changed. OTOH the layout object can - * also change and it could still be the same layoutid. - */ - - KLGetKeyboardLayoutProperty(currentLayout, kKLIdentifier, - (const void**)¤tLayoutId); - - if ((lastLayout != currentLayout) - || (lastLayoutId != currentLayoutId)) { - -#ifdef TK_MAC_DEBUG_KEYBOARD - fprintf (stderr, "GetKeyboardLayout(): Use KLS\n"); -#endif + /* + * Use the Keyboard Layout Services. + */ - hasLayoutChanged = true; - - /* - * Reinitialize all relevant variables. - */ - - lastLayout = currentLayout; - lastLayoutId = currentLayoutId; - uchr = NULL; - KCHR = NULL; - - if ((KLGetKeyboardLayoutProperty(currentLayout, - kKLuchrData, (const void**)&uchr) - == noErr) - && (uchr != NULL)) { - /* done */ - } else if ((KLGetKeyboardLayoutProperty(currentLayout, - kKLKCHRData, (const void**)&KCHR) - == noErr) - && (KCHR != NULL)) { - /* done */ - } - } - } + KLGetCurrentKeyboardLayout(¤tLayout); - } else { + if (currentLayout != NULL) { - /* - * Use the classic approach as shown in Apple code samples, loading - * the keyboard resources directly. This is broken for 10.3 and - * possibly already in 10.2. - */ + /* + * The layout pointer could in theory be the same for different + * layouts, only the id gives us the information that the + * keyboard has actually changed. OTOH the layout object can + * also change and it could still be the same layoutid. + */ - currentLayoutId = GetScriptVariable(currentKeyScript,smScriptKeys); + KLGetKeyboardLayoutProperty(currentLayout, kKLIdentifier, + (const void**)¤tLayoutId); - if ((lastLayout == NULL) || (lastLayoutId != currentLayoutId)) { + if ((lastLayout != currentLayout) + || (lastLayoutId != currentLayoutId)) { #ifdef TK_MAC_DEBUG_KEYBOARD - fprintf (stderr, "GetKeyboardLayout(): Use GetResource()\n"); + TkMacOSXDbgMsg("Use KLS"); #endif - hasLayoutChanged = true; - - /* - * Reinitialize all relevant variables. - */ - - lastLayout = (KeyboardLayoutRef)-1; - lastLayoutId = currentLayoutId; - uchr = NULL; - KCHR = NULL; - - /* - * Get the new layout resource in the classic way. - */ - - if (handle != NULL) { - HUnlock(handle); - } - - if ((handle = GetResource('uchr',currentLayoutId)) != NULL) { - HLock(handle); - uchr = *handle; - } else if ((handle = GetResource('KCHR',currentLayoutId)) != NULL) { - HLock(handle); - KCHR = *handle; - } - } + hasLayoutChanged = true; + + /* + * Reinitialize all relevant variables. + */ + + lastLayout = currentLayout; + lastLayoutId = currentLayoutId; + uchr = NULL; + KCHR = NULL; + + if ((KLGetKeyboardLayoutProperty(currentLayout, + kKLuchrData, (const void**)&uchr) + == noErr) + && (uchr != NULL)) { + /* done */ + } else if ((KLGetKeyboardLayoutProperty(currentLayout, + kKLKCHRData, (const void**)&KCHR) + == noErr) + && (KCHR != NULL)) { + /* done */ + } + } } if (hasLayoutChanged) { - #ifdef TK_MAC_DEBUG_KEYBOARD - if (KCHR != NULL) { - fprintf (stderr, "GetKeyboardLayout(): New 'KCHR' layout %d\n", - (int) (short) currentLayoutId); - } else if (uchr != NULL) { - fprintf (stderr, "GetKeyboardLayout(): New 'uchr' layout %d\n", - (int) (short) currentLayoutId); - } else { - fprintf (stderr, "GetKeyboardLayout(): Use cached layout " - "(should have been %d)\n", - (int) (short) currentLayoutId); - } + if (KCHR) { + TkMacOSXDbgMsg("New 'KCHR' layout %ld", currentLayoutId); + } else if (uchr) { + TkMacOSXDbgMsg("New 'uchr' layout %ld", currentLayoutId); + } else { + TkMacOSXDbgMsg("Use cached layout (should have been %ld)", + currentLayoutId); + } #endif - deadKeyStateUp = deadKeyStateDown = 0; + deadKeyStateUp = deadKeyStateDown = 0; - /* - * If we did get a new 'KCHR', compute its encoding and put it into - * lastEncoding. - * - * If we didn't get a new 'KCHR' and if we have no 'uchr' either, get - * some 'KCHR' from the OS cache and leave lastEncoding at its - * current value. This should better not happen, it doesn't really - * work. - */ + /* + * If we did get a new 'KCHR', compute its encoding and put it into + * lastEncoding. + * + * If we didn't get a new 'KCHR' and if we have no 'uchr' either, get + * some 'KCHR' from the OS cache and leave lastEncoding at its + * current value. This should better not happen, it doesn't really + * work. + */ - if (KCHR != NULL) { - lastEncoding = GetKCHREncoding(currentKeyScript, currentLayoutId); + if (KCHR) { + lastEncoding = GetKCHREncoding(currentKeyScript, currentLayoutId); #ifdef TK_MAC_DEBUG_KEYBOARD - fprintf (stderr, "GetKeyboardLayout(): New 'KCHR' encoding %lu " - "(%lu + 0x%lX)\n", - lastEncoding, lastEncoding & 0xFFFFL, - lastEncoding & ~0xFFFFL); + TkMacOSXDbgMsg("New 'KCHR' encoding %lu (%lu + 0x%lX)", + lastEncoding, lastEncoding & 0xFFFFL, + lastEncoding & ~0xFFFFL); #endif - } else if (uchr == NULL) { - KCHR = (Ptr) GetScriptManagerVariable(smKCHRCache); - } + } else if (!uchr) { + KCHR = (Ptr)(intptr_t)GetScriptManagerVariable(smKCHRCache); + } } - if (uchr != NULL) { - *resourcePtr = uchr; - return 1; + if (uchr) { + *resourcePtr = uchr; + return 1; } else { - *resourcePtr = KCHR; - *encodingPtr = lastEncoding; - return 0; + *resourcePtr = KCHR; + *encodingPtr = lastEncoding; + return 0; } } - /* *---------------------------------------------------------------------- * * GetKCHREncoding -- * - * Upgrade a WorldScript code to a TEC encoding based on the keyboard - * layout id. + * Upgrade a WorldScript code to a TEC encoding based on the keyboard + * layout id. * * Results: - * The TEC code that corresponds best to the combination of WorldScript - * code and 'KCHR' id. + * The TEC code that corresponds best to the combination of WorldScript + * code and 'KCHR' id. * * Side effects: - * None. + * None. * * Rationale and Notes: - * WorldScript codes are sometimes not unique encodings. E.g. Icelandic - * uses script smRoman (0), but the actual encoding is - * kTextEncodingMacIcelandic (37). ftp://ftp.unicode.org/Public - * /MAPPINGS/VENDORS/APPLE/README.TXT has a good summary of these - * variants. So we need to upgrade the script to an encoding with - * GetTextEncodingFromScriptInfo(). + * WorldScript codes are sometimes not unique encodings. E.g. Icelandic + * uses script smRoman (0), but the actual encoding is + * kTextEncodingMacIcelandic (37). ftp://ftp.unicode.org/Public + * /MAPPINGS/VENDORS/APPLE/README.TXT has a good summary of these + * variants. So we need to upgrade the script to an encoding with + * GetTextEncodingFromScriptInfo(). * - * 'KCHR' ids are usually region codes (see the comments in Script.h). - * Where they are not, we get a paramErr from the OS function and have - * appropriate fallbacks. + * 'KCHR' ids are usually region codes (see the comments in Script.h). + * Where they are not, we get a paramErr from the OS function and have + * appropriate fallbacks. * *---------------------------------------------------------------------- */ static TextEncoding -GetKCHREncoding(ScriptCode script, SInt32 layoutid) +GetKCHREncoding( + ScriptCode script, + SInt32 layoutid) { RegionCode region = layoutid; TextEncoding encoding = script; if (GetTextEncodingFromScriptInfo(script, kTextLanguageDontCare, region, - &encoding) == noErr) { - return encoding; + &encoding) == noErr) { + return encoding; } /* * GetTextEncodingFromScriptInfo() doesn't know about more exotic - * layouts. This provides a fallback for good measure. In an ideal + * layouts. This provides a fallback for good measure. In an ideal * world, exotic layouts would always provide a 'uchr' resource anyway, * so we wouldn't need this. * - * We can add more keyboard layouts, if we get actual complaints. Farsi + * We can add more keyboard layouts, if we get actual complaints. Farsi * or other Celtic/Gaelic layouts would be candidates. */ switch (layoutid) { - - /* - * Icelandic and Faroese (planned). These layouts are sold by Apple - * Iceland for legacy applications. - */ - - case 1800: case 1821: - return kTextEncodingMacIcelandic; - - /* - * Irish and Welsh. These layouts are mentioned in . - * - * FIXME: This may have to be kTextEncodingMacGaelic instead, but I - * can't locate layouts of this type for testing. - */ - - case 581: case 779: - return kTextEncodingMacCeltic; + /* + * Icelandic and Faroese (planned). These layouts are sold by Apple + * Iceland for legacy applications. + */ + + case 1800: case 1821: + return kTextEncodingMacIcelandic; + + /* + * Irish and Welsh. These layouts are mentioned in . + * + * FIXME: This may have to be kTextEncodingMacGaelic instead, but I + * can't locate layouts of this type for testing. + */ + + case 581: case 779: + return kTextEncodingMacCeltic; } - + /* * The valid script codes are also the valid default encoding codes, so * if nothing else helps, fall back on those. @@ -854,275 +729,266 @@ GetKCHREncoding(ScriptCode script, SInt32 layoutid) return script; } - /* *---------------------------------------------------------------------- * * KeycodeToUnicodeViaUnicodeResource -- * - * Given MacOS key event data this function generates the Unicode - * characters. It does this using a 'uchr' and the UCKeyTranslate - * API. + * Given MacOS key event data this function generates the Unicode + * characters. It does this using a 'uchr' and the UCKeyTranslate + * API. * - * The parameter deadKeyStatePtr can be NULL, if no deadkey handling - * is needed. + * The parameter deadKeyStatePtr can be NULL, if no deadkey handling + * is needed. * - * Tested and known to work with US, Hebrew, Greek and Russian layouts - * as well as "Unicode Hex Input". + * Tested and known to work with US, Hebrew, Greek and Russian layouts + * as well as "Unicode Hex Input". * * Results: - * The number of characters generated if any, 0 if we are waiting for - * another byte of a dead-key sequence. Fills in the uniChars array - * with a Unicode string. + * The number of characters generated if any, 0 if we are waiting for + * another byte of a dead-key sequence. Fills in the uniChars array + * with a Unicode string. * * Side Effects: - * None + * None * *---------------------------------------------------------------------- */ static int KeycodeToUnicodeViaUnicodeResource( - UniChar * uniChars, int maxChars, - Ptr uchr, - EventKind eKind, - UInt32 keycode, UInt32 modifiers, - UInt32 * deadKeyStatePtr) + UniChar *uniChars, + int maxChars, + Ptr uchr, + EventKind eKind, + UInt32 keycode, + UInt32 modifiers, + UInt32 *deadKeyStatePtr) { int action; unsigned long keyboardType; OptionBits options = 0; UInt32 dummy_state; - UniCharCount actuallength; - OSStatus status; + UniCharCount actuallength; + OSStatus err; keycode &= 0xFF; modifiers = (modifiers >> 8) & 0xFF; keyboardType = LMGetKbdType(); if (NULL==deadKeyStatePtr) { - options = kUCKeyTranslateNoDeadKeysMask; - dummy_state = 0; - deadKeyStatePtr = &dummy_state; + options = kUCKeyTranslateNoDeadKeysMask; + dummy_state = 0; + deadKeyStatePtr = &dummy_state; } - switch(eKind) { - case kEventRawKeyDown: - action = kUCKeyActionDown; - break; - case kEventRawKeyUp: - action = kUCKeyActionUp; - break; - case kEventRawKeyRepeat: - action = kUCKeyActionAutoKey; - break; - default: -#ifdef TK_MAC_DEBUG - fprintf (stderr, - "KeycodeToUnicodeViaUnicodeResource(): " - "Invalid parameter eKind %d\n", - (int) eKind); -#endif - return 0; + switch(eKind) { + case kEventRawKeyDown: + action = kUCKeyActionDown; + break; + case kEventRawKeyUp: + action = kUCKeyActionUp; + break; + case kEventRawKeyRepeat: + action = kUCKeyActionAutoKey; + break; + default: + TkMacOSXDbgMsg("Invalid parameter eKind %d", eKind); + return 0; } - status = UCKeyTranslate( - (const UCKeyboardLayout *) uchr, - keycode, action, modifiers, keyboardType, - options, deadKeyStatePtr, - maxChars, &actuallength, uniChars); + err = ChkErr(UCKeyTranslate, (const UCKeyboardLayout *) uchr, keycode, + action, modifiers, keyboardType, options, deadKeyStatePtr, + maxChars, &actuallength, uniChars); if ((0 == actuallength) && (0 != *deadKeyStatePtr)) { - /* - * More data later - */ - - return 0; + /* + * More data later + */ + + return 0; } - + /* * some IMEs leave residue :-( */ - - *deadKeyStatePtr = 0; - if (noErr != status) { -#ifdef TK_MAC_DEBUG - fprintf(stderr,"UCKeyTranslate failed: %d", (int) status); -#endif - actuallength = 0; + *deadKeyStatePtr = 0; + + if (err != noErr) { + actuallength = 0; } return actuallength; } - /* *---------------------------------------------------------------------- * * KeycodeToUnicodeViaKCHRResource -- * - * Given MacOS key event data this function generates the Unicode - * characters. It does this using a 'KCHR' and the KeyTranslate API. + * Given MacOS key event data this function generates the Unicode + * characters. It does this using a 'KCHR' and the KeyTranslate API. * - * The parameter deadKeyStatePtr can be NULL, if no deadkey handling - * is needed. + * The parameter deadKeyStatePtr can be NULL, if no deadkey handling + * is needed. * * Results: - * The number of characters generated if any, 0 if we are waiting for - * another byte of a dead-key sequence. Fills in the uniChars array - * with a Unicode string. + * The number of characters generated if any, 0 if we are waiting for + * another byte of a dead-key sequence. Fills in the uniChars array + * with a Unicode string. * * Side Effects: - * None + * None * *---------------------------------------------------------------------- */ static int KeycodeToUnicodeViaKCHRResource( - UniChar * uniChars, int maxChars, - Ptr kchr, TextEncoding encoding, - EventKind eKind, - UInt32 keycode, UInt32 modifiers, - UInt32 * deadKeyStatePtr) + UniChar *uniChars, + int maxChars, + Ptr kchr, + TextEncoding encoding, + EventKind eKind, + UInt32 keycode, + UInt32 modifiers, + UInt32 *deadKeyStatePtr) { UInt32 result; char macBuff[3]; - char * macStr; + char *macStr; int macStrLen; UInt32 dummy_state = 0; - if (NULL == deadKeyStatePtr) { - deadKeyStatePtr = &dummy_state; + deadKeyStatePtr = &dummy_state; } keycode |= modifiers; result = KeyTranslate(kchr, keycode, deadKeyStatePtr); if ((0 == result) && (0 != dummy_state)) { - /* - * 'dummy_state' gets only filled if the caller did not want deadkey - * processing (deadKeyStatePtr was NULL originally), but we still - * have a deadkey. We just push the keycode for the space bar to get - * the real key value. - */ - - result = KeyTranslate(kchr, 0x31, deadKeyStatePtr); - *deadKeyStatePtr = 0; + /* + * 'dummy_state' gets only filled if the caller did not want deadkey + * processing (deadKeyStatePtr was NULL originally), but we still + * have a deadkey. We just push the keycode for the space bar to get + * the real key value. + */ + + result = KeyTranslate(kchr, 0x31, deadKeyStatePtr); + *deadKeyStatePtr = 0; } if ((0 == result) && (0 != *deadKeyStatePtr)) { - /* - * More data later - */ - - return 0; + /* + * More data later + */ + + return 0; } macBuff[0] = (char) (result >> 16); - macBuff[1] = (char) result; + macBuff[1] = (char) result; macBuff[2] = 0; if (0 != macBuff[0]) { - /* - * If the first byte is valid, the second is too - */ - - macStr = macBuff; - macStrLen = 2; + /* + * If the first byte is valid, the second is too + */ + + macStr = macBuff; + macStrLen = 2; } else if (0 != macBuff[1]) { - /* - * Only the second is valid - */ - - macStr = macBuff+1; - macStrLen = 1; + /* + * Only the second is valid + */ + + macStr = macBuff+1; + macStrLen = 1; } else { - /* - * No valid bytes at all -- shouldn't happen - */ - - macStr = NULL; - macStrLen = 0; + /* + * No valid bytes at all -- shouldn't happen + */ + + macStr = NULL; + macStrLen = 0; } if (macStrLen <= 0) { - return 0; + return 0; } else { - /* - * Use the CFString conversion routines. This is the easiest and - * most compatible way to get from an 8-bit string and a MacOS script - * code to a Unicode string. - * - * FIXME: The system ships with an Irish 'KCHR' but without the - * corresponding macCeltic encoding, which triggers the error below. - * Tcl doesn't have the macCeltic encoding either right now, so until - * we get that, we can just as well stick to this code. The right - * fix would be to use the Tcl encodings and add macCeltic and - * probably others there. Suitable Unicode data files for the - * missing encodings are available from www.evertype.com. - */ - - CFStringRef cfString; - int uniStrLen; - - cfString = CFStringCreateWithCStringNoCopy( - NULL, macStr, encoding, kCFAllocatorNull); - if (cfString == NULL) { -#ifdef TK_MAC_DEBUG - fprintf(stderr, "CFString: Can't convert with encoding %d\n", - (int) encoding); -#endif - return 0; - } + /* + * Use the CFString conversion routines. This is the easiest and + * most compatible way to get from an 8-bit string and a MacOS script + * code to a Unicode string. + * + * FIXME: The system ships with an Irish 'KCHR' but without the + * corresponding macCeltic encoding, which triggers the error below. + * Tcl doesn't have the macCeltic encoding either right now, so until + * we get that, we can just as well stick to this code. The right + * fix would be to use the Tcl encodings and add macCeltic and + * probably others there. Suitable Unicode data files for the + * missing encodings are available from www.evertype.com. + */ + + CFStringRef cfString; + int uniStrLen; + + cfString = CFStringCreateWithCStringNoCopy(NULL, macStr, encoding, + kCFAllocatorNull); + if (cfString == NULL) { + TkMacOSXDbgMsg("CFString: Can't convert with encoding %ld", + encoding); + return 0; + } - uniStrLen = CFStringGetLength(cfString); - if (uniStrLen > maxChars) { - uniStrLen = maxChars; - } - CFStringGetCharacters(cfString, CFRangeMake(0,uniStrLen), uniChars); - CFRelease(cfString); + uniStrLen = CFStringGetLength(cfString); + if (uniStrLen > maxChars) { + uniStrLen = maxChars; + } + CFStringGetCharacters(cfString, CFRangeMake(0,uniStrLen), uniChars); + CFRelease(cfString); - return uniStrLen; + return uniStrLen; } } - /* *---------------------------------------------------------------------- * * TkMacOSXKeycodeToUnicode -- * - * Given MacOS key event data this function generates the Unicode - * characters. It does this using OS resources and APIs. + * Given MacOS key event data this function generates the Unicode + * characters. It does this using OS resources and APIs. * - * The parameter deadKeyStatePtr can be NULL, if no deadkey handling - * is needed. + * The parameter deadKeyStatePtr can be NULL, if no deadkey handling + * is needed. * - * This function is called from XKeycodeToKeysym() in - * tkMacOSKeyboard.c. + * This function is called from XKeycodeToKeysym() in + * tkMacOSKeyboard.c. * * Results: - * The number of characters generated if any, 0 if we are waiting for - * another byte of a dead-key sequence. Fills in the uniChars array - * with a Unicode string. + * The number of characters generated if any, 0 if we are waiting for + * another byte of a dead-key sequence. Fills in the uniChars array + * with a Unicode string. * * Side Effects: - * None + * None * *---------------------------------------------------------------------- */ MODULE_SCOPE int TkMacOSXKeycodeToUnicode( - UniChar * uniChars, int maxChars, - EventKind eKind, - UInt32 keycode, UInt32 modifiers, - UInt32 * deadKeyStatePtr) + UniChar *uniChars, + int maxChars, + EventKind eKind, + UInt32 keycode, + UInt32 modifiers, + UInt32 *deadKeyStatePtr) { Ptr resource = NULL; TextEncoding encoding; @@ -1130,32 +996,30 @@ TkMacOSXKeycodeToUnicode( if (GetKeyboardLayout(&resource,&encoding)) { - len = KeycodeToUnicodeViaUnicodeResource( - uniChars, maxChars, resource, eKind, - keycode, modifiers, deadKeyStatePtr); + len = KeycodeToUnicodeViaUnicodeResource( + uniChars, maxChars, resource, eKind, + keycode, modifiers, deadKeyStatePtr); } else { - len = KeycodeToUnicodeViaKCHRResource( - uniChars, maxChars, resource, encoding, eKind, - keycode, modifiers, deadKeyStatePtr); + len = KeycodeToUnicodeViaKCHRResource( + uniChars, maxChars, resource, encoding, eKind, + keycode, modifiers, deadKeyStatePtr); } return len; } - - /* *---------------------------------------------------------------------- * * XGrabKeyboard -- * - * Simulates a keyboard grab by setting the focus. + * Simulates a keyboard grab by setting the focus. * * Results: - * Always returns GrabSuccess. + * Always returns GrabSuccess. * * Side effects: - * Sets the keyboard focus to the specified window. + * Sets the keyboard focus to the specified window. * *---------------------------------------------------------------------- */ @@ -1169,7 +1033,7 @@ XGrabKeyboard( int keyboard_mode, Time time) { - gKeyboardWinPtr = Tk_IdToWindow(display, grab_window); + keyboardGrabWinPtr = Tk_IdToWindow(display, grab_window); return GrabSuccess; } @@ -1178,13 +1042,13 @@ XGrabKeyboard( * * XUngrabKeyboard -- * - * Releases the simulated keyboard grab. + * Releases the simulated keyboard grab. * * Results: - * None. + * None. * * Side effects: - * Sets the keyboard focus back to the value before the grab. + * Sets the keyboard focus back to the value before the grab. * *---------------------------------------------------------------------- */ @@ -1194,7 +1058,7 @@ XUngrabKeyboard( Display* display, Time time) { - gKeyboardWinPtr = NULL; + keyboardGrabWinPtr = NULL; } /* @@ -1203,15 +1067,16 @@ XUngrabKeyboard( * TkMacOSXGetCapture -- * * Results: - * Returns the current grab window + * Returns the current grab window * Side effects: - * None. + * None. * */ + Tk_Window -TkMacOSXGetCapture() +TkMacOSXGetCapture(void) { - return gGrabWinPtr; + return grabWinPtr; } /* @@ -1219,28 +1084,46 @@ TkMacOSXGetCapture() * * TkpSetCapture -- * - * This function captures the mouse so that all future events - * will be reported to this window, even if the mouse is outside - * the window. If the specified window is NULL, then the mouse - * is released. + * This function captures the mouse so that all future events + * will be reported to this window, even if the mouse is outside + * the window. If the specified window is NULL, then the mouse + * is released. * * Results: - * None. + * None. * * Side effects: - * Sets the capture flag and captures the mouse. + * Sets the capture flag and captures the mouse. * *---------------------------------------------------------------------- */ void TkpSetCapture( - TkWindow *winPtr) /* Capture window, or NULL. */ + TkWindow *winPtr) /* Capture window, or NULL. */ { - while ((winPtr != NULL) && !Tk_IsTopLevel(winPtr)) { - winPtr = winPtr->parentPtr; + while (winPtr && !Tk_IsTopLevel(winPtr)) { + winPtr = winPtr->parentPtr; } - gGrabWinPtr = (Tk_Window) winPtr; +#if 0 + { + TkWindow *w = NULL; + WindowModality m; + + if (winPtr) { + w = winPtr; + m = kWindowModalityAppModal; + } else if (grabWinPtr) { + w = (TkWindow*)grabWinPtr; + m = kWindowModalityNone; + } + if (w && w->window != None && TkMacOSXHostToplevelExists(w)) { + ChkErr(SetWindowModality, GetWindowFromPort( + TkMacOSXGetDrawablePort(w->window)), m, NULL); + } + } +#endif + grabWinPtr = (Tk_Window) winPtr; } /* @@ -1248,25 +1131,25 @@ TkpSetCapture( * * Tk_SetCaretPos -- * - * This enables correct placement of the XIM caret. This is called - * by widgets to indicate their cursor placement, and the caret - * location is used by TkpGetString to place the XIM caret. + * This enables correct placement of the XIM caret. This is called + * by widgets to indicate their cursor placement, and the caret + * location is used by TkpGetString to place the XIM caret. * * Results: - * None + * None * * Side effects: - * None + * None * *---------------------------------------------------------------------- */ void -Tk_SetCaretPos(tkwin, x, y, height) - Tk_Window tkwin; - int x; - int y; - int height; +Tk_SetCaretPos( + Tk_Window tkwin, + int x, + int y, + int height) { } @@ -1275,23 +1158,23 @@ Tk_SetCaretPos(tkwin, x, y, height) * * TkMacOSXInitKeyboard -- * - * This procedure initializes the keyboard layout. + * This procedure initializes the keyboard layout. * * Results: - * None. + * None. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ MODULE_SCOPE void -TkMacOSXInitKeyboard ( - Tcl_Interp *interp) +TkMacOSXInitKeyboard( + Tcl_Interp *interp) { Ptr resource; TextEncoding encoding; - - GetKeyboardLayout(&resource,&encoding); + + GetKeyboardLayout(&resource, &encoding); } diff --git a/macosx/tkMacOSXKeyboard.c b/macosx/tkMacOSXKeyboard.c index e767dbf..ce16324 100644 --- a/macosx/tkMacOSXKeyboard.c +++ b/macosx/tkMacOSXKeyboard.c @@ -1,20 +1,21 @@ -/* +/* * tkMacOSXKeyboard.c -- * - * Routines to support keyboard events on the Macintosh. + * Routines to support keyboard events on the Macintosh. * * Copyright (c) 1995-1997 Sun Microsystems, Inc. * Copyright 2001, Apple Computer, Inc. + * Copyright (c) 2005-2007 Daniel A. Steffen * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkMacOSXKeyboard.c,v 1.20 2006/07/21 06:26:28 das Exp $ + * RCS: @(#) $Id: tkMacOSXKeyboard.c,v 1.21 2007/04/23 21:24:33 das Exp $ */ #include "tkMacOSXInt.h" -#include "tkMacOSXEvent.h" /* TkMacOSXKeycodeToUnicode() FIXME: That - * function should probably move here. */ +#include "tkMacOSXEvent.h" /* TkMacOSXKeycodeToUnicode() FIXME: That + * function should probably move here. */ /* * A couple of simple definitions to make code a bit more self-explaining. @@ -23,22 +24,22 @@ * tkMacOSXMouseEvent.c. */ -#define LATIN1_MAX 255 -#define MAC_KEYCODE_MAX 0x7F +#define LATIN1_MAX 255 +#define MAC_KEYCODE_MAX 0x7F #define MAC_KEYCODE_MASK 0x7F -#define COMMAND_MASK Mod1Mask -#define OPTION_MASK Mod2Mask +#define COMMAND_MASK Mod1Mask +#define OPTION_MASK Mod2Mask /* - * Tables enumerating the special keys defined on Mac keyboards. These are + * Tables enumerating the special keys defined on Mac keyboards. These are * necessary for correct keysym mappings for all keys where the keysyms are * not identical with their ASCII or Latin-1 code points. */ typedef struct { - int keycode; /* Macintosh keycode. */ - KeySym keysym; /* X windows keysym. */ + int keycode; /* Macintosh keycode. */ + KeySym keysym; /* X windows keysym. */ } KeyInfo; /* @@ -55,64 +56,64 @@ typedef struct { */ static KeyInfo keyArray[] = { - {0x24, XK_Return}, - {0x30, XK_Tab}, - {0x33, XK_BackSpace}, - {0x34, XK_Return}, - {0x35, XK_Escape}, - - {0x47, XK_Clear}, - {0x4C, XK_KP_Enter}, - - {0x72, XK_Help}, - {0x73, XK_Home}, - {0x74, XK_Page_Up}, - {0x75, XK_Delete}, - {0x77, XK_End}, - {0x79, XK_Page_Down}, - - {0x7B, XK_Left}, - {0x7C, XK_Right}, - {0x7D, XK_Down}, - {0x7E, XK_Up}, - - {0, 0} + {0x24, XK_Return}, + {0x30, XK_Tab}, + {0x33, XK_BackSpace}, + {0x34, XK_Return}, + {0x35, XK_Escape}, + + {0x47, XK_Clear}, + {0x4C, XK_KP_Enter}, + + {0x72, XK_Help}, + {0x73, XK_Home}, + {0x74, XK_Page_Up}, + {0x75, XK_Delete}, + {0x77, XK_End}, + {0x79, XK_Page_Down}, + + {0x7B, XK_Left}, + {0x7C, XK_Right}, + {0x7D, XK_Down}, + {0x7E, XK_Up}, + + {0, 0} }; static KeyInfo virtualkeyArray[] = { - {122, XK_F1}, - {120, XK_F2}, - {99, XK_F3}, - {118, XK_F4}, - {96, XK_F5}, - {97, XK_F6}, - {98, XK_F7}, - {100, XK_F8}, - {101, XK_F9}, - {109, XK_F10}, - {103, XK_F11}, - {111, XK_F12}, - {105, XK_F13}, - {107, XK_F14}, - {113, XK_F15}, - {0, 0} + {122, XK_F1}, + {120, XK_F2}, + {99, XK_F3}, + {118, XK_F4}, + {96, XK_F5}, + {97, XK_F6}, + {98, XK_F7}, + {100, XK_F8}, + {101, XK_F9}, + {109, XK_F10}, + {103, XK_F11}, + {111, XK_F12}, + {105, XK_F13}, + {107, XK_F14}, + {113, XK_F15}, + {0, 0} }; static int initialized = 0; -static Tcl_HashTable keycodeTable; /* keyArray hashed by keycode value. */ -static Tcl_HashTable vkeyTable; /* virtualkeyArray hashed by virtual - * keycode value. */ +static Tcl_HashTable keycodeTable; /* keyArray hashed by keycode value. */ +static Tcl_HashTable vkeyTable; /* virtualkeyArray hashed by virtual + * keycode value. */ -static int latin1Table[LATIN1_MAX+1]; /* Reverse mapping table for - * controls, ASCII and Latin-1. */ +static int latin1Table[LATIN1_MAX+1]; /* Reverse mapping table for + * controls, ASCII and Latin-1. */ /* * Prototypes for static functions used in this file. */ -static void InitKeyMaps (void); -static void InitLatin1Table(Display *display); -static int XKeysymToMacKeycode(Display *display, KeySym keysym); +static void InitKeyMaps (void); +static void InitLatin1Table(Display *display); +static int XKeysymToMacKeycode(Display *display, KeySym keysym); /* @@ -120,39 +121,39 @@ static int XKeysymToMacKeycode(Display *display, KeySym keysym); * * InitKeyMaps -- * - * Creates hash tables used by some of the functions in this file. + * Creates hash tables used by some of the functions in this file. * - * FIXME: As keycodes are defined to be in the limited range 0-127, it - * would be easier and more efficient to use directly initialized plain - * arrays and drop this function. + * FIXME: As keycodes are defined to be in the limited range 0-127, it + * would be easier and more efficient to use directly initialized plain + * arrays and drop this function. * * Results: - * None. + * None. * * Side effects: - * Allocates memory & creates some hash tables. + * Allocates memory & creates some hash tables. * *---------------------------------------------------------------------- */ static void -InitKeyMaps() +InitKeyMaps(void) { Tcl_HashEntry *hPtr; KeyInfo *kPtr; int dummy; - + Tcl_InitHashTable(&keycodeTable, TCL_ONE_WORD_KEYS); for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) { - hPtr = Tcl_CreateHashEntry(&keycodeTable, (char *) kPtr->keycode, - &dummy); - Tcl_SetHashValue(hPtr, kPtr->keysym); + hPtr = Tcl_CreateHashEntry(&keycodeTable, (char *) kPtr->keycode, + &dummy); + Tcl_SetHashValue(hPtr, kPtr->keysym); } Tcl_InitHashTable(&vkeyTable, TCL_ONE_WORD_KEYS); for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) { - hPtr = Tcl_CreateHashEntry(&vkeyTable, (char *) kPtr->keycode, - &dummy); - Tcl_SetHashValue(hPtr, kPtr->keysym); + hPtr = Tcl_CreateHashEntry(&vkeyTable, (char *) kPtr->keycode, + &dummy); + Tcl_SetHashValue(hPtr, kPtr->keysym); } initialized = 1; } @@ -162,16 +163,16 @@ InitKeyMaps() * * InitLatin1Table -- * - * Creates a simple table to be used for mapping from keysyms to - * keycodes. Always needs to be called before using latin1Table, - * because the keyboard layout may have changed, and than the table must - * be re-computed. + * Creates a simple table to be used for mapping from keysyms to + * keycodes. Always needs to be called before using latin1Table, + * because the keyboard layout may have changed, and than the table must + * be re-computed. * * Results: - * None. + * None. * * Side effects: - * Sets the global latin1Table. + * Sets the global latin1Table. * *---------------------------------------------------------------------- */ @@ -190,46 +191,46 @@ InitLatin1Table( keyLayoutID = GetScriptVariable(keyScript,smScriptKeys); if (!latin1_initialized || (lastKeyLayoutID != keyLayoutID)) { - int keycode; - KeySym keysym; - int state; - int modifiers; - - latin1_initialized = true; - lastKeyLayoutID = keyLayoutID; - - memset(latin1Table, 0, sizeof(latin1Table)); - - /* - * In the common X11 implementations, a keymap has four columns - * "plain", "Shift", "Mode_switch" and "Mode_switch + Shift". We - * don't use "Mode_switch", but we use "Option" instead. (This is - * similar to Apple's X11 implementation, where "Mode_switch" is used - * as an alias for "Option".) - * - * So here we go through all 4 columns of the keymap and find all - * Latin-1 compatible keycodes. We go through the columns - * back-to-front from the more exotic columns to the more simple, so - * that simple keycode-modifier combinations are preferred in the - * resulting table. - */ - - for (state = 3; state >= 0; state--) { - modifiers = 0; - if (state & 1) { - modifiers |= shiftKey; - } - if (state & 2) { - modifiers |= optionKey; - } - - for (keycode = 0; keycode <= MAC_KEYCODE_MAX; keycode++) { - keysym = XKeycodeToKeysym(display,keycode<<16,state); - if (keysym <= LATIN1_MAX) { - latin1Table[keysym] = keycode | modifiers; - } - } - } + int keycode; + KeySym keysym; + int state; + int modifiers; + + latin1_initialized = true; + lastKeyLayoutID = keyLayoutID; + + memset(latin1Table, 0, sizeof(latin1Table)); + + /* + * In the common X11 implementations, a keymap has four columns + * "plain", "Shift", "Mode_switch" and "Mode_switch + Shift". We + * don't use "Mode_switch", but we use "Option" instead. (This is + * similar to Apple's X11 implementation, where "Mode_switch" is used + * as an alias for "Option".) + * + * So here we go through all 4 columns of the keymap and find all + * Latin-1 compatible keycodes. We go through the columns + * back-to-front from the more exotic columns to the more simple, so + * that simple keycode-modifier combinations are preferred in the + * resulting table. + */ + + for (state = 3; state >= 0; state--) { + modifiers = 0; + if (state & 1) { + modifiers |= shiftKey; + } + if (state & 2) { + modifiers |= optionKey; + } + + for (keycode = 0; keycode <= MAC_KEYCODE_MAX; keycode++) { + keysym = XKeycodeToKeysym(display,keycode<<16,state); + if (keysym <= LATIN1_MAX) { + latin1Table[keysym] = keycode | modifiers; + } + } + } } } @@ -238,19 +239,19 @@ InitLatin1Table( * * XKeycodeToKeysym -- * - * Translate from a system-dependent keycode to a system-independent - * keysym. + * Translate from a system-dependent keycode to a system-independent + * keysym. * * Results: - * Returns the translated keysym, or NoSymbol on failure. + * Returns the translated keysym, or NoSymbol on failure. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ -KeySym +KeySym XKeycodeToKeysym( Display* display, KeyCode keycode, @@ -263,55 +264,55 @@ XKeycodeToKeysym( (void) display; /*unused*/ if (!initialized) { - InitKeyMaps(); + InitKeyMaps(); } /* * When determining what keysym to produce we first check to see if the - * key is a function key. We then check to see if the character is - * another non-printing key. Finally, we return the key syms for all + * key is a function key. We then check to see if the character is + * another non-printing key. Finally, we return the key syms for all * ASCII and Latin-1 chars. */ newKeycode = keycode >> 16; if ((keycode & 0xFFFF) == 0x10) { - hPtr = Tcl_FindHashEntry(&vkeyTable, (char *) newKeycode); - if (hPtr != NULL) { - return (KeySym) Tcl_GetHashValue(hPtr); - } + hPtr = Tcl_FindHashEntry(&vkeyTable, (char *) newKeycode); + if (hPtr != NULL) { + return (KeySym) Tcl_GetHashValue(hPtr); + } } hPtr = Tcl_FindHashEntry(&keycodeTable, (char *) newKeycode); if (hPtr != NULL) { - return (KeySym) Tcl_GetHashValue(hPtr); + return (KeySym) Tcl_GetHashValue(hPtr); } - /* + /* * Add in the Mac modifier flags for shift and option. */ if (index & 1) { - newKeycode |= shiftKey; + newKeycode |= shiftKey; } if (index & 2) { - newKeycode |= optionKey; + newKeycode |= optionKey; } newChar = 0; TkMacOSXKeycodeToUnicode( - &newChar, 1, kEventRawKeyDown, - newKeycode & 0x00FF, newKeycode & 0xFF00, NULL); + &newChar, 1, kEventRawKeyDown, + newKeycode & 0x00FF, newKeycode & 0xFF00, NULL); /* - * X11 keysyms are identical to Unicode for ASCII and Latin-1. Give up + * X11 keysyms are identical to Unicode for ASCII and Latin-1. Give up * for other characters for now. */ if ((newChar >= XK_space) && (newChar <= LATIN1_MAX)) { - return newChar; + return newChar; } - return NoSymbol; + return NoSymbol; } /* @@ -319,24 +320,24 @@ XKeycodeToKeysym( * * TkpGetString -- * - * Retrieve the string equivalent for the given keyboard event. + * Retrieve the string equivalent for the given keyboard event. * * Results: - * Returns the UTF string. + * Returns the UTF string. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ char * TkpGetString( - TkWindow *winPtr, /* Window where event occurred: Needed to get - * input context. */ - XEvent *eventPtr, /* X keyboard event. */ - Tcl_DString *dsPtr) /* Uninitialized or empty string to hold - * result. */ + TkWindow *winPtr, /* Window where event occurred: Needed to get + * input context. */ + XEvent *eventPtr, /* X keyboard event. */ + Tcl_DString *dsPtr) /* Uninitialized or empty string to hold + * result. */ { (void) winPtr; /*unused*/ Tcl_DStringInit(dsPtr); @@ -348,28 +349,28 @@ TkpGetString( * * XGetModifierMapping -- * - * Fetch the current keycodes used as modifiers. + * Fetch the current keycodes used as modifiers. * * Results: - * Returns a new modifier map. + * Returns a new modifier map. * * Side effects: - * Allocates a new modifier map data structure. + * Allocates a new modifier map data structure. * *---------------------------------------------------------------------- */ -XModifierKeymap * +XModifierKeymap * XGetModifierMapping( Display* display) -{ +{ XModifierKeymap * modmap; (void) display; /*unused*/ /* * MacOSX doesn't use the key codes for the modifiers for anything, and - * we don't generate them either. So there is no modifier map. + * we don't generate them either. So there is no modifier map. */ modmap = (XModifierKeymap *) ckalloc(sizeof(XModifierKeymap)); @@ -383,23 +384,23 @@ XGetModifierMapping( * * XFreeModifiermap -- * - * Deallocate a modifier map that was created by XGetModifierMapping. + * Deallocate a modifier map that was created by XGetModifierMapping. * * Results: - * None. + * None. * * Side effects: - * Frees the datastructure referenced by modmap. + * Frees the datastructure referenced by modmap. * *---------------------------------------------------------------------- */ -void +void XFreeModifiermap( XModifierKeymap *modmap) { if (modmap->modifiermap != NULL) { - ckfree((char *) modmap->modifiermap); + ckfree((char *) modmap->modifiermap); } ckfree((char *) modmap); } @@ -409,31 +410,31 @@ XFreeModifiermap( * * XKeysymToString, XStringToKeysym -- * - * These X window functions map keysyms to strings & strings to keysyms. - * However, Tk already does this for the most common keysyms. - * Therefore, these functions only need to support keysyms that will be - * specific to the Macintosh. Currently, there are none. + * These X window functions map keysyms to strings & strings to keysyms. + * However, Tk already does this for the most common keysyms. + * Therefore, these functions only need to support keysyms that will be + * specific to the Macintosh. Currently, there are none. * * Results: - * None. + * None. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ -char * +char * XKeysymToString( KeySym keysym) { - return NULL; + return NULL; } -KeySym +KeySym XStringToKeysym( const char* string) -{ +{ return NoSymbol; } @@ -442,15 +443,15 @@ XStringToKeysym( * * XKeysymToMacKeycode -- * - * An internal function like XKeysymToKeycode but only generating the - * Mac specific keycode plus the modifiers Shift and Option. + * An internal function like XKeysymToKeycode but only generating the + * Mac specific keycode plus the modifiers Shift and Option. * * Results: - * A Mac keycode with the actual keycode in the low byte and Mac-style - * modifier bits in the high byte. + * A Mac keycode with the actual keycode in the low byte and Mac-style + * modifier bits in the high byte. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ @@ -462,42 +463,42 @@ XKeysymToMacKeycode( { if (keysym <= LATIN1_MAX) { - /* - * Handle keysyms in the Latin-1 range where keysym and Unicode - * character code point are the same. - */ + /* + * Handle keysyms in the Latin-1 range where keysym and Unicode + * character code point are the same. + */ - InitLatin1Table(display); - return latin1Table[keysym]; + InitLatin1Table(display); + return latin1Table[keysym]; } else { - /* - * Handle special keys from our exception tables. Don't mind if this - * is slow, neither the test suite nor [event generate] need to be - * optimized (we hope). - */ - - KeyInfo *kPtr; - - for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) { - if (kPtr->keysym == keysym) { - return kPtr->keycode; - } - } - for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) { - if (kPtr->keysym == keysym) { - return kPtr->keycode; - } - } - - /* - * For other keysyms (not Latin-1 and not special keys), we'd need a - * generic keysym-to-unicode table. We don't have that, so we give - * up here. - */ - - return 0; + /* + * Handle special keys from our exception tables. Don't mind if this + * is slow, neither the test suite nor [event generate] need to be + * optimized (we hope). + */ + + KeyInfo *kPtr; + + for (kPtr = keyArray; kPtr->keycode != 0; kPtr++) { + if (kPtr->keysym == keysym) { + return kPtr->keycode; + } + } + for (kPtr = virtualkeyArray; kPtr->keycode != 0; kPtr++) { + if (kPtr->keysym == keysym) { + return kPtr->keycode; + } + } + + /* + * For other keysyms (not Latin-1 and not special keys), we'd need a + * generic keysym-to-unicode table. We don't have that, so we give + * up here. + */ + + return 0; } } @@ -506,17 +507,17 @@ XKeysymToMacKeycode( * * XKeysymToKeycode -- * - * The function XKeysymToKeycode takes an X11 keysym and converts it - * into a Mac keycode. It is in the stubs table for compatibility but - * not used anywhere in the core. + * The function XKeysymToKeycode takes an X11 keysym and converts it + * into a Mac keycode. It is in the stubs table for compatibility but + * not used anywhere in the core. * * Results: - * A 32 bit keycode with the the mac keycode (without modifiers) in the - * higher 16 bits of the keycode and the ASCII or Latin-1 code in the - * lower 8 bits of the keycode. + * A 32 bit keycode with the the mac keycode (without modifiers) in the + * higher 16 bits of the keycode and the ASCII or Latin-1 code in the + * lower 8 bits of the keycode. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ @@ -528,17 +529,17 @@ XKeysymToKeycode( { int macKeycode = XKeysymToMacKeycode(display, keysym); KeyCode result; - + /* - * See also TkpSetKeycodeAndState. The 0x0010 magic is used in - * XKeycodeToKeysym. For special keys like XK_Return the lower 8 bits of + * See also TkpSetKeycodeAndState. The 0x0010 magic is used in + * XKeycodeToKeysym. For special keys like XK_Return the lower 8 bits of * the keysym are usually a related ASCII control code. */ if ((keysym >= XK_F1) && (keysym <= XK_F35)) { - result = 0x0010; + result = 0x0010; } else { - result = 0x00FF & keysym; + result = 0x00FF & keysym; } result |= (macKeycode & MAC_KEYCODE_MASK) << 16; @@ -549,23 +550,23 @@ XKeysymToKeycode( NB: Keep this commented code for a moment for reference. if ((keysym >= XK_space) && (XK_asciitilde)) { - if (keysym == 'a') { - virtualKeyCode = 0x00; - } else if (keysym == 'b' || keysym == 'B') { - virtualKeyCode = 0x0B; - } else if (keysym == 'c') { - virtualKeyCode = 0x08; - } else if (keysym == 'x' || keysym == 'X') { - virtualKeyCode = 0x07; - } else if (keysym == 'z') { - virtualKeyCode = 0x06; - } else if (keysym == ' ') { - virtualKeyCode = 0x31; - } else if (keysym == XK_Return) { - virtualKeyCode = 0x24; - keysym = '\r'; - } - keycode = keysym + (virtualKeyCode <<16); + if (keysym == 'a') { + virtualKeyCode = 0x00; + } else if (keysym == 'b' || keysym == 'B') { + virtualKeyCode = 0x0B; + } else if (keysym == 'c') { + virtualKeyCode = 0x08; + } else if (keysym == 'x' || keysym == 'X') { + virtualKeyCode = 0x07; + } else if (keysym == 'z') { + virtualKeyCode = 0x06; + } else if (keysym == ' ') { + virtualKeyCode = 0x31; + } else if (keysym == XK_Return) { + virtualKeyCode = 0x24; + keysym = '\r'; + } + keycode = keysym + (virtualKeyCode <<16); } return keycode; @@ -576,19 +577,19 @@ NB: Keep this commented code for a moment for reference. * * TkpSetKeycodeAndState -- * - * The function TkpSetKeycodeAndState takes a keysym and fills in the - * appropriate members of an XEvent. It is similar to XKeysymToKeycode, - * but it also sets the modifier mask in the XEvent. It is used by - * [event generate] and it is in the stubs table. + * The function TkpSetKeycodeAndState takes a keysym and fills in the + * appropriate members of an XEvent. It is similar to XKeysymToKeycode, + * but it also sets the modifier mask in the XEvent. It is used by + * [event generate] and it is in the stubs table. * * Results: - * Fills an XEvent, sets the member xkey.keycode with a keycode - * formatted the same as XKeysymToKeycode and the member xkey.state with - * the modifiers implied by the keysym. Also fills in xkey.trans_chars, - * so that the actual characters can be retrieved later. + * Fills an XEvent, sets the member xkey.keycode with a keycode + * formatted the same as XKeysymToKeycode and the member xkey.state with + * the modifiers implied by the keysym. Also fills in xkey.trans_chars, + * so that the actual characters can be retrieved later. * * Side effects: - * None. + * None. * *---------------------------------------------------------------------- */ @@ -600,36 +601,36 @@ TkpSetKeycodeAndState( XEvent *eventPtr) { if (keysym == NoSymbol) { - eventPtr->xkey.keycode = 0; + eventPtr->xkey.keycode = 0; } else { - Display *display = Tk_Display(tkwin); - int macKeycode = XKeysymToMacKeycode(display, keysym); - - /* - * See also XKeysymToKeycode. - */ - - if ((keysym >= XK_F1) && (keysym <= XK_F35)) { - eventPtr->xkey.keycode = 0x0010; - } else { - eventPtr->xkey.keycode = 0x00FF & keysym; - } - eventPtr->xkey.keycode |= (macKeycode & MAC_KEYCODE_MASK) << 16; - - if (shiftKey & macKeycode) { - eventPtr->xkey.state |= ShiftMask; - } - if (optionKey & macKeycode) { - eventPtr->xkey.state |= OPTION_MASK; - } - - if (keysym <= LATIN1_MAX) { - int done; - done = Tcl_UniCharToUtf(keysym,eventPtr->xkey.trans_chars); - eventPtr->xkey.trans_chars[done] = 0; - } else { - eventPtr->xkey.trans_chars[0] = 0; - } + Display *display = Tk_Display(tkwin); + int macKeycode = XKeysymToMacKeycode(display, keysym); + + /* + * See also XKeysymToKeycode. + */ + + if ((keysym >= XK_F1) && (keysym <= XK_F35)) { + eventPtr->xkey.keycode = 0x0010; + } else { + eventPtr->xkey.keycode = 0x00FF & keysym; + } + eventPtr->xkey.keycode |= (macKeycode & MAC_KEYCODE_MASK) << 16; + + if (shiftKey & macKeycode) { + eventPtr->xkey.state |= ShiftMask; + } + if (optionKey & macKeycode) { + eventPtr->xkey.state |= OPTION_MASK; + } + + if (keysym <= LATIN1_MAX) { + int done; + done = Tcl_UniCharToUtf(keysym,eventPtr->xkey.trans_chars); + eventPtr->xkey.trans_chars[done] = 0; + } else { + eventPtr->xkey.trans_chars[0] = 0; + } } } @@ -638,24 +639,24 @@ TkpSetKeycodeAndState( * * TkpGetKeySym -- * - * Given an X KeyPress or KeyRelease event, map the keycode in the event - * into a keysym. + * Given an X KeyPress or KeyRelease event, map the keycode in the event + * into a keysym. * * Results: - * The return value is the keysym corresponding to eventPtr, or NoSymbol - * if no matching keysym could be found. + * The return value is the keysym corresponding to eventPtr, or NoSymbol + * if no matching keysym could be found. * * Side effects: - * In the first call for a given display, keycode-to-keysym maps get - * loaded. + * In the first call for a given display, keycode-to-keysym maps get + * loaded. * *---------------------------------------------------------------------- */ KeySym TkpGetKeySym( - TkDisplay *dispPtr, /* Display in which to map keycode. */ - XEvent *eventPtr) /* Description of X event. */ + TkDisplay *dispPtr, /* Display in which to map keycode. */ + XEvent *eventPtr) /* Description of X event. */ { KeySym sym; int index; @@ -665,50 +666,50 @@ TkpGetKeySym( */ if (dispPtr->bindInfoStale) { - TkpInitKeymapInfo(dispPtr); + TkpInitKeymapInfo(dispPtr); } /* - * Handle pure modifier keys specially. We use -1 as a signal for + * Handle pure modifier keys specially. We use -1 as a signal for * this. */ if (eventPtr->xany.send_event == -1) { - int modifier = eventPtr->xkey.keycode; - if (modifier == cmdKey) { - return XK_Meta_L; - } else if (modifier == shiftKey) { - return XK_Shift_L; - } else if (modifier == alphaLock) { - return XK_Caps_Lock; - } else if (modifier == optionKey) { - return XK_Alt_L; - } else if (modifier == controlKey) { - return XK_Control_L; - } else if (modifier == kEventKeyModifierNumLockMask) { - return XK_Num_Lock; - } else if (modifier == kEventKeyModifierFnMask) { - return XK_Super_L; - } else if (modifier == rightShiftKey) { - return XK_Shift_R; - } else if (modifier == rightOptionKey) { - return XK_Alt_R; - } else if (modifier == rightControlKey) { - return XK_Control_R; - } else { - - /* - * If we get here, we probably need to implement something new. - */ - - return NoSymbol; - } + int modifier = eventPtr->xkey.keycode; + if (modifier == cmdKey) { + return XK_Meta_L; + } else if (modifier == shiftKey) { + return XK_Shift_L; + } else if (modifier == alphaLock) { + return XK_Caps_Lock; + } else if (modifier == optionKey) { + return XK_Alt_L; + } else if (modifier == controlKey) { + return XK_Control_L; + } else if (modifier == kEventKeyModifierNumLockMask) { + return XK_Num_Lock; + } else if (modifier == kEventKeyModifierFnMask) { + return XK_Super_L; + } else if (modifier == rightShiftKey) { + return XK_Shift_R; + } else if (modifier == rightOptionKey) { + return XK_Alt_R; + } else if (modifier == rightControlKey) { + return XK_Control_R; + } else { + + /* + * If we get here, we probably need to implement something new. + */ + + return NoSymbol; + } } /* * Figure out which of the four slots in the keymap vector to use for - * this key. Refer to Xlib documentation for more info on how this - * computation works. (Note: We use "Option" in keymap columns 2 and 3 + * this key. Refer to Xlib documentation for more info on how this + * computation works. (Note: We use "Option" in keymap columns 2 and 3 * where other implementations have "Mode_switch".) */ @@ -721,14 +722,14 @@ TkpGetKeySym( #if 0 if (eventPtr->xkey.state & OPTION_MASK) { - index |= 2; + index |= 2; } #endif if ((eventPtr->xkey.state & ShiftMask) - || (/* (dispPtr->lockUsage != LU_IGNORE) - && */ (eventPtr->xkey.state & LockMask))) { - index |= 1; + || (/* (dispPtr->lockUsage != LU_IGNORE) + && */ (eventPtr->xkey.state & LockMask))) { + index |= 1; } /* @@ -744,20 +745,20 @@ TkpGetKeySym( */ if ((index & 1) && !(eventPtr->xkey.state & ShiftMask) - /*&& (dispPtr->lockUsage == LU_CAPS)*/ ) { - - /* - * FIXME: Keysyms are only identical to Unicode for ASCII and - * Latin-1, so we can't use Tcl_UniCharIsUpper() for keysyms outside - * that range. This may be a serious problem here. - */ - - if ((sym == NoSymbol) || (sym > LATIN1_MAX) - || !Tcl_UniCharIsUpper(sym)) { - index &= ~1; - sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, - index); - } + /*&& (dispPtr->lockUsage == LU_CAPS)*/ ) { + + /* + * FIXME: Keysyms are only identical to Unicode for ASCII and + * Latin-1, so we can't use Tcl_UniCharIsUpper() for keysyms outside + * that range. This may be a serious problem here. + */ + + if ((sym == NoSymbol) || (sym > LATIN1_MAX) + || !Tcl_UniCharIsUpper(sym)) { + index &= ~1; + sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, + index); + } } /* @@ -766,8 +767,8 @@ TkpGetKeySym( */ if ((index & 1) && (sym == NoSymbol)) { - sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, - index & ~1); + sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, + index & ~1); } return sym; } @@ -777,30 +778,30 @@ TkpGetKeySym( * * TkpInitKeymapInfo -- * - * This procedure is invoked to scan keymap information to recompute - * stuff that's important for binding, such as the modifier key (if any) - * that corresponds to the "Mode_switch" keysym. + * This procedure is invoked to scan keymap information to recompute + * stuff that's important for binding, such as the modifier key (if any) + * that corresponds to the "Mode_switch" keysym. * * Results: - * None. + * None. * * Side effects: - * Keymap-related information in dispPtr is updated. + * Keymap-related information in dispPtr is updated. * *-------------------------------------------------------------- */ void TkpInitKeymapInfo( - TkDisplay *dispPtr) /* Display for which to recompute keymap - * information. */ + TkDisplay *dispPtr) /* Display for which to recompute keymap + * information. */ { dispPtr->bindInfoStale = 0; /* * Behaviours that are variable on X11 are defined constant on MacOSX. * lockUsage is only used above in TkpGetKeySym(), nowhere else - * currently. There is no offical "Mode_switch" key. + * currently. There is no offical "Mode_switch" key. */ dispPtr->lockUsage = LU_CAPS; @@ -810,9 +811,9 @@ TkpInitKeymapInfo( /* * With this, and become synonyms for and