diff options
Diffstat (limited to 'macosx')
52 files changed, 40452 insertions, 0 deletions
diff --git a/macosx/Makefile b/macosx/Makefile new file mode 100644 index 0000000..dc4f77f --- /dev/null +++ b/macosx/Makefile @@ -0,0 +1,56 @@ +################################################################################ +# +# Simple makefile for building on Mac OS X with the +# Project Builder command line tool 'pbxbuild' +# +# RCS: @(#) $Id: Makefile,v 1.2 2002/08/31 06:12:29 das Exp $ +# +################################################################################ + +INSTALL_ROOT = + +BUILD_DIR = ../../build + +TARGET = Wish + +DEVBUILDSTYLE = Development +DEPBUILDSTYLE = Deployment + +PBXBUILD = /usr/bin/pbxbuild + +BUILD = ${PBXBUILD} SYMROOT="${BUILD_DIR}" -target "${TARGET}" + +DEVBUILD = ${BUILD} -buildstyle "${DEVBUILDSTYLE}" +DEPBUILD = ${BUILD} -buildstyle "${DEPBUILDSTYLE}" + +INSTALLOPTS = INSTALL_ROOT="${INSTALL_ROOT}" + +################################################################################ + +all: develop deploy + +install: install-develop install-deploy + +clean: clean-develop clean-deploy + +################################################################################ + +develop: + ${DEVBUILD} + +deploy: + ${DEPBUILD} + +install-develop: + ${DEVBUILD} install ${INSTALLOPTS} + +install-deploy: + ${DEPBUILD} install ${INSTALLOPTS} + +clean-develop: + ${DEVBUILD} clean + +clean-deploy: + ${DEPBUILD} clean + +################################################################################ diff --git a/macosx/Wish.icns b/macosx/Wish.icns Binary files differnew file mode 100644 index 0000000..060bfbd --- /dev/null +++ b/macosx/Wish.icns diff --git a/macosx/Wish.pbproj/jingham.pbxuser b/macosx/Wish.pbproj/jingham.pbxuser new file mode 100644 index 0000000..72932e7 --- /dev/null +++ b/macosx/Wish.pbproj/jingham.pbxuser @@ -0,0 +1,1502 @@ +// !$*UTF8*$! +{ + 005751A902FB00920AC916F0 = { + fRef = F5375568016C376E01DC9062; + isa = PBXTextBookmark; + name = "tkMacOSXXStubs.c: TkpCloseDisplay"; + rLen = 0; + rLoc = 5311; + rType = 0; + vrLen = 417; + vrLoc = 4894; + }; + F50D961501961F0201DC9062 = { + fileReference = F5375551016C376E01DC9062; + isa = PBXFileBreakpoint; + lineNumber = 902; + state = 2; + }; + F537552A016C352C01DC9062 = { + activeBuildStyle = F537552C016C352C01DC9062; + activeExecutable = F53756AB016C4DD401DC9062; + activeTarget = F53756A0016C4DD401DC9062; + addToTargets = ( + F53755DF016C38D201DC9062, + ); + breakpoints = ( + F5B2CDC10175829501DC9062, + F571FE470179562E01DC9062, + F571FE4A0179695001DC9062, + F571FE4C01796B1101DC9062, + F571FE4D01796CAF01DC9062, + F571FE4E01796F9201DC9062, + F571FE4F0179702301DC9062, + F571FE500179702301DC9062, + F583DC0E018D092D01DC9062, + F583DC0F018D0CB501DC9062, + F583DC13018D2B4A01DC9062, + F58907BE018DCE8F01DC9062, + F58907C5018DD1C301DC9062, + F50D961501961F0201DC9062, + F566083B0197283B01DC9062, + F566083C0197823801DC9062, + F5A5146F01D05DC201DC9062, + F5A5147001D0758C01DC9062, + F5A852D6020F6C6C01DC9062, + F5A439C0029B609C01DC9064, + F5A439C2029B60ED01DC9064, + F5A439CA029B620901DC9064, + F55BC4B602B2DFB901DC9062, + F5978FD602B3190701DC9062, + ); + executables = ( + F53756AB016C4DD401DC9062, + ); + perUserDictionary = { + PBXPerProjectTemplateStateSaveDate = 49921092; + "PBXTemplateGeometry-F5314676015831810DCA290F" = { + ContentSize = "{716, 618}"; + LeftSlideOut = { + Collapsed = NO; + Frame = "{{0, 23}, {716, 595}}"; + Split0 = { + ActiveTab = 2; + Collapsed = NO; + Frame = "{{0, 0}, {716, 595}}"; + Split0 = { + Frame = "{{0, 249}, {716, 346}}"; + }; + SplitCount = 1; + Tab0 = { + Debugger = { + Collapsed = NO; + Frame = "{{0, 0}, {952, 321}}"; + Split0 = { + Frame = "{{0, 24}, {952, 297}}"; + Split0 = { + Frame = "{{0, 0}, {468, 297}}"; + }; + Split1 = { + DebugVariablesTableConfiguration = ( + Name, + 126.803, + Value, + 150.074, + Summary, + 172.123, + ); + Frame = "{{477, 0}, {475, 297}}"; + }; + SplitCount = 2; + }; + SplitCount = 1; + Tab0 = { + Frame = "{{0, 0}, {100, 50}}"; + }; + Tab1 = { + Frame = "{{0, 0}, {100, 50}}"; + }; + TabCount = 2; + TabsVisible = YES; + }; + Frame = "{{0, 0}, {952, 321}}"; + LauncherConfigVersion = 7; + }; + Tab1 = { + Frame = "{{0, 0}, {781, 452}}"; + LauncherConfigVersion = 3; + Runner = { + Frame = "{{0, 0}, {781, 452}}"; + }; + }; + Tab2 = { + BuildMessageFrame = "{{0, 0}, {718, 0}}"; + BuildTranscriptFrame = "{{0, 9}, {718, 236}}"; + Frame = "{{0, 0}, {716, 243}}"; + }; + Tab3 = { + Frame = "{{0, 0}, {612, 295}}"; + }; + TabCount = 4; + TabsVisible = NO; + }; + SplitCount = 1; + Tab0 = { + Frame = "{{0, 0}, {300, 533}}"; + GroupTreeTableConfiguration = ( + SCMStatusColumn, + 22, + TargetStatusColumn, + 18, + MainColumn, + 245, + ); + }; + Tab1 = { + ClassesFrame = "{{0, 0}, {280, 398}}"; + ClassesTreeTableConfiguration = ( + PBXBookColumnIdentifier, + 20, + PBXClassColumnIdentifier, + 237, + ); + Frame = "{{0, 0}, {278, 659}}"; + MembersFrame = "{{0, 407}, {280, 252}}"; + MembersTreeTableConfiguration = ( + PBXBookColumnIdentifier, + 20, + PBXMethodColumnIdentifier, + 236, + ); + }; + Tab2 = { + Frame = "{{0, 0}, {200, 100}}"; + }; + Tab3 = { + Frame = "{{0, 0}, {200, 100}}"; + TargetTableConfiguration = ( + ActiveObject, + 16, + ObjectNames, + 202.296, + ); + }; + Tab4 = { + BreakpointsTreeTableConfiguration = ( + breakpointColumn, + 197, + enabledColumn, + 31, + ); + Frame = "{{0, 0}, {250, 100}}"; + }; + TabCount = 5; + TabsVisible = NO; + }; + StatusViewVisible = YES; + Template = F5314676015831810DCA290F; + ToolbarVisible = YES; + WindowLocation = "{49, 213}"; + }; + "PBXTemplateGeometry-F5CA7ECB015C094F0DCA290F" = { + ContentSize = "{690, 721}"; + LeftSlideOut = { + Collapsed = NO; + Frame = "{{0, 0}, {690, 721}}"; + Split0 = { + Collapsed = NO; + Frame = "{{0, 0}, {690, 721}}"; + Split0 = { + Frame = "{{0, 0}, {690, 721}}"; + }; + SplitCount = 1; + Tab0 = { + Debugger = { + Collapsed = NO; + Frame = "{{0, 0}, {484, 208}}"; + Split0 = { + Frame = "{{0, 24}, {484, 184}}"; + Split0 = { + Frame = "{{0, 0}, {236, 184}}"; + }; + Split1 = { + DebugVariablesTableConfiguration = ( + Name, + 123, + Value, + 85, + Summary, + 62.123, + ); + Frame = "{{245, 0}, {239, 184}}"; + }; + SplitCount = 2; + }; + SplitCount = 1; + Tab0 = { + Frame = "{{0, 0}, {100, 50}}"; + }; + Tab1 = { + Frame = "{{0, 0}, {100, 50}}"; + }; + TabCount = 2; + TabsVisible = YES; + }; + Frame = "{{0, 0}, {484, 208}}"; + LauncherConfigVersion = 7; + }; + Tab1 = { + Frame = "{{0, 0}, {664, 208}}"; + LauncherConfigVersion = 3; + Runner = { + Frame = "{{0, 0}, {664, 208}}"; + }; + }; + Tab2 = { + BuildMessageFrame = "{{0, 0}, {666, 43}}"; + BuildTranscriptFrame = "{{0, 52}, {666, 0}}"; + Frame = "{{0, 0}, {664, 50}}"; + }; + Tab3 = { + Frame = "{{0, 0}, {612, 295}}"; + }; + TabCount = 4; + TabsVisible = NO; + }; + SplitCount = 1; + Tab0 = { + Frame = "{{0, 0}, {313, 531}}"; + GroupTreeTableConfiguration = ( + SCMStatusColumn, + 22, + TargetStatusColumn, + 18, + MainColumn, + 258, + ); + }; + Tab1 = { + ClassesFrame = "{{0, 0}, {280, 398}}"; + ClassesTreeTableConfiguration = ( + PBXBookColumnIdentifier, + 20, + PBXClassColumnIdentifier, + 237, + ); + Frame = "{{0, 0}, {278, 659}}"; + MembersFrame = "{{0, 407}, {280, 252}}"; + MembersTreeTableConfiguration = ( + PBXBookColumnIdentifier, + 20, + PBXMethodColumnIdentifier, + 236, + ); + }; + Tab2 = { + Frame = "{{0, 0}, {200, 100}}"; + }; + Tab3 = { + Frame = "{{0, 0}, {200, 557}}"; + TargetTableConfiguration = ( + ActiveObject, + 16, + ObjectNames, + 202.296, + ); + }; + Tab4 = { + BreakpointsTreeTableConfiguration = ( + breakpointColumn, + 197, + enabledColumn, + 31, + ); + Frame = "{{0, 0}, {250, 100}}"; + }; + TabCount = 5; + TabsVisible = NO; + }; + StatusViewVisible = NO; + Template = F5CA7ECB015C094F0DCA290F; + ToolbarVisible = NO; + WindowLocation = "{48, 3}"; + }; + PBXWorkspaceContents = ( + { + LeftSlideOut = { + Split0 = { + Split0 = { + NavContent0 = { + history = ( + F5A439D1029B6B5501DC9064, + F5A439D2029B6B5501DC9064, + F5A439D3029B6B5501DC9064, + F5A439D4029B6B5501DC9064, + F5A439D5029B6B5501DC9064, + F5A439D6029B6B5501DC9064, + F5A439D7029B6B5501DC9064, + F5BE671E029B6FEE01DC9064, + F55BC4B902B2E09101DC9062, + F55BC4BA02B2E09101DC9062, + F55BC4BD02B2E09101DC9062, + F5BFE59402F984FA01DC9062, + F5BFE59502F984FA01DC9062, + F5BFE59602F984FA01DC9062, + F5BFE59702F984FA01DC9062, + F5BFE59802F984FA01DC9062, + F5BFE59902F984FA01DC9062, + F5BFE59B02F984FA01DC9062, + F5BFE59C02F984FA01DC9062, + F5BFE59D02F984FA01DC9062, + F5BFE59E02F984FA01DC9062, + F5BFE59F02F984FA01DC9062, + F5BFE5A002F984FA01DC9062, + F5BFE5A102F984FA01DC9062, + F5BFE5A202F984FA01DC9062, + F5BFE5A402F984FA01DC9062, + F5BFE5A502F984FA01DC9062, + F5BFE5A602F984FA01DC9062, + F5BFE5A702F984FA01DC9062, + F5BFE5A802F984FA01DC9062, + ); + prevStack = ( + F5A439DA029B6B5501DC9064, + F5A439DB029B6B5501DC9064, + F5A439DE029B6B5501DC9064, + F5A439DF029B6B5501DC9064, + F5A439E0029B6B5501DC9064, + F5A439E1029B6B5501DC9064, + F5A439E2029B6B5501DC9064, + F5A439E3029B6B5501DC9064, + F5A439E4029B6B5501DC9064, + F5A439E5029B6B5501DC9064, + F5A439E6029B6B5501DC9064, + F5A439E7029B6B5501DC9064, + F5A439E8029B6B5501DC9064, + F5BE671F029B6FEE01DC9064, + F55BC4BF02B2E09101DC9062, + F55BC4C002B2E09101DC9062, + F55BC4C102B2E09101DC9062, + F55BC4C202B2E09101DC9062, + F55BC4C302B2E09101DC9062, + F55BC4C402B2E09101DC9062, + F55BC4C702B2E09101DC9062, + F5BFE5AA02F984FA01DC9062, + F5BFE5AB02F984FA01DC9062, + F5BFE5AC02F984FA01DC9062, + F5BFE5AD02F984FA01DC9062, + F5BFE5AE02F984FA01DC9062, + F5BFE5AF02F984FA01DC9062, + F5BFE5B002F984FA01DC9062, + F5BFE5B202F984FA01DC9062, + F5BFE5B302F984FA01DC9062, + F5BFE5B402F984FA01DC9062, + F5BFE5B502F984FA01DC9062, + F5BFE5B702F984FA01DC9062, + F5BFE5B802F984FA01DC9062, + F5BFE5B902F984FA01DC9062, + F5BFE5BB02F984FA01DC9062, + F5BFE5BC02F984FA01DC9062, + F5BFE5BD02F984FA01DC9062, + F5BFE5BE02F984FA01DC9062, + F5BFE5BF02F984FA01DC9062, + F5BFE5C002F984FA01DC9062, + F5BFE5C102F984FA01DC9062, + ); + }; + NavContent1 = { + bookmark = 005751A902FB00920AC916F0; + history = ( + F5BFE5C402F984FA01DC9062, + ); + }; + NavCount = 2; + NavGeometry0 = { + Frame = "{{0, 0}, {645, 321}}"; + NavBarVisible = YES; + }; + NavGeometry1 = { + Frame = "{{0, 330}, {645, 321}}"; + NavBarVisible = YES; + }; + }; + SplitCount = 1; + Tab0 = { + Debugger = { + Split0 = { + SplitCount = 2; + }; + SplitCount = 1; + TabCount = 2; + }; + LauncherConfigVersion = 7; + }; + Tab1 = { + LauncherConfigVersion = 3; + Runner = { + }; + }; + TabCount = 4; + }; + SplitCount = 1; + Tab1 = { + OptionsSetName = "Default Options"; + }; + TabCount = 5; + }; + }, + ); + PBXWorkspaceGeometries = ( + { + ContentSize = "{929, 674}"; + LeftSlideOut = { + ActiveTab = 0; + Collapsed = NO; + Frame = "{{0, 23}, {929, 651}}"; + Split0 = { + Collapsed = NO; + Frame = "{{284, 0}, {645, 651}}"; + Split0 = { + Frame = "{{0, 0}, {645, 651}}"; + }; + SplitCount = 1; + Tab0 = { + Debugger = { + Collapsed = NO; + Frame = "{{0, 0}, {681, 289}}"; + Split0 = { + Frame = "{{0, 24}, {681, 265}}"; + Split0 = { + Frame = "{{0, 0}, {333, 265}}"; + }; + Split1 = { + DebugVariablesTableConfiguration = ( + Name, + 82.80298, + Value, + 104.074, + Summary, + 126.123, + ); + Frame = "{{342, 0}, {339, 265}}"; + }; + SplitCount = 2; + }; + SplitCount = 1; + Tab0 = { + Frame = "{{0, 0}, {100, 50}}"; + }; + Tab1 = { + Frame = "{{0, 0}, {100, 50}}"; + }; + TabCount = 2; + TabsVisible = YES; + }; + Frame = "{{0, 0}, {681, 289}}"; + LauncherConfigVersion = 7; + }; + Tab1 = { + Frame = "{{0, 0}, {681, 120}}"; + LauncherConfigVersion = 3; + Runner = { + Frame = "{{0, 0}, {681, 120}}"; + }; + }; + Tab2 = { + BuildMessageFrame = "{{0, 0}, {683, 127}}"; + BuildTranscriptFrame = "{{0, 136}, {683, 100}}"; + Frame = "{{0, 0}, {681, 234}}"; + }; + Tab3 = { + Frame = "{{0, 0}, {681, 238}}"; + }; + TabCount = 4; + TabsVisible = NO; + }; + SplitCount = 1; + Tab0 = { + Frame = "{{0, 0}, {260, 651}}"; + GroupTreeTableConfiguration = ( + SCMStatusColumn, + 22, + TargetStatusColumn, + 18, + MainColumn, + 205, + ); + }; + Tab1 = { + ClassesFrame = "{{0, 0}, {250, 333}}"; + ClassesTreeTableConfiguration = ( + PBXBookColumnIdentifier, + 20, + PBXClassColumnIdentifier, + 207, + ); + Frame = "{{0, 0}, {248, 554}}"; + MembersFrame = "{{0, 342}, {250, 212}}"; + MembersTreeTableConfiguration = ( + PBXBookColumnIdentifier, + 20, + PBXMethodColumnIdentifier, + 206, + ); + }; + Tab2 = { + Frame = "{{0, 0}, {217, 554}}"; + }; + Tab3 = { + Frame = "{{0, 0}, {239, 651}}"; + TargetTableConfiguration = ( + ActiveObject, + 16, + ObjectNames, + 206.296, + ); + }; + Tab4 = { + BreakpointsTreeTableConfiguration = ( + breakpointColumn, + 197, + enabledColumn, + 31, + ); + Frame = "{{0, 0}, {250, 554}}"; + }; + TabCount = 5; + TabsVisible = YES; + }; + StatusViewVisible = YES; + Template = 64ABBB4501FA494900185B06; + ToolbarVisible = YES; + WindowLocation = "{165, 176}"; + }, + ); + PBXWorkspaceStateSaveDate = 49921092; + }; + perUserProjectItems = { + 005751A902FB00920AC916F0 = 005751A902FB00920AC916F0; + F55BC4B902B2E09101DC9062 = F55BC4B902B2E09101DC9062; + F55BC4BA02B2E09101DC9062 = F55BC4BA02B2E09101DC9062; + F55BC4BD02B2E09101DC9062 = F55BC4BD02B2E09101DC9062; + F55BC4BF02B2E09101DC9062 = F55BC4BF02B2E09101DC9062; + F55BC4C002B2E09101DC9062 = F55BC4C002B2E09101DC9062; + F55BC4C102B2E09101DC9062 = F55BC4C102B2E09101DC9062; + F55BC4C202B2E09101DC9062 = F55BC4C202B2E09101DC9062; + F55BC4C302B2E09101DC9062 = F55BC4C302B2E09101DC9062; + F55BC4C402B2E09101DC9062 = F55BC4C402B2E09101DC9062; + F55BC4C702B2E09101DC9062 = F55BC4C702B2E09101DC9062; + F5A439D1029B6B5501DC9064 = F5A439D1029B6B5501DC9064; + F5A439D2029B6B5501DC9064 = F5A439D2029B6B5501DC9064; + F5A439D3029B6B5501DC9064 = F5A439D3029B6B5501DC9064; + F5A439D4029B6B5501DC9064 = F5A439D4029B6B5501DC9064; + F5A439D5029B6B5501DC9064 = F5A439D5029B6B5501DC9064; + F5A439D6029B6B5501DC9064 = F5A439D6029B6B5501DC9064; + F5A439D7029B6B5501DC9064 = F5A439D7029B6B5501DC9064; + F5A439DA029B6B5501DC9064 = F5A439DA029B6B5501DC9064; + F5A439DB029B6B5501DC9064 = F5A439DB029B6B5501DC9064; + F5A439DE029B6B5501DC9064 = F5A439DE029B6B5501DC9064; + F5A439DF029B6B5501DC9064 = F5A439DF029B6B5501DC9064; + F5A439E0029B6B5501DC9064 = F5A439E0029B6B5501DC9064; + F5A439E1029B6B5501DC9064 = F5A439E1029B6B5501DC9064; + F5A439E2029B6B5501DC9064 = F5A439E2029B6B5501DC9064; + F5A439E3029B6B5501DC9064 = F5A439E3029B6B5501DC9064; + F5A439E4029B6B5501DC9064 = F5A439E4029B6B5501DC9064; + F5A439E5029B6B5501DC9064 = F5A439E5029B6B5501DC9064; + F5A439E6029B6B5501DC9064 = F5A439E6029B6B5501DC9064; + F5A439E7029B6B5501DC9064 = F5A439E7029B6B5501DC9064; + F5A439E8029B6B5501DC9064 = F5A439E8029B6B5501DC9064; + F5BE671E029B6FEE01DC9064 = F5BE671E029B6FEE01DC9064; + F5BE671F029B6FEE01DC9064 = F5BE671F029B6FEE01DC9064; + F5BFE59402F984FA01DC9062 = F5BFE59402F984FA01DC9062; + F5BFE59502F984FA01DC9062 = F5BFE59502F984FA01DC9062; + F5BFE59602F984FA01DC9062 = F5BFE59602F984FA01DC9062; + F5BFE59702F984FA01DC9062 = F5BFE59702F984FA01DC9062; + F5BFE59802F984FA01DC9062 = F5BFE59802F984FA01DC9062; + F5BFE59902F984FA01DC9062 = F5BFE59902F984FA01DC9062; + F5BFE59B02F984FA01DC9062 = F5BFE59B02F984FA01DC9062; + F5BFE59C02F984FA01DC9062 = F5BFE59C02F984FA01DC9062; + F5BFE59D02F984FA01DC9062 = F5BFE59D02F984FA01DC9062; + F5BFE59E02F984FA01DC9062 = F5BFE59E02F984FA01DC9062; + F5BFE59F02F984FA01DC9062 = F5BFE59F02F984FA01DC9062; + F5BFE5A002F984FA01DC9062 = F5BFE5A002F984FA01DC9062; + F5BFE5A102F984FA01DC9062 = F5BFE5A102F984FA01DC9062; + F5BFE5A202F984FA01DC9062 = F5BFE5A202F984FA01DC9062; + F5BFE5A402F984FA01DC9062 = F5BFE5A402F984FA01DC9062; + F5BFE5A502F984FA01DC9062 = F5BFE5A502F984FA01DC9062; + F5BFE5A602F984FA01DC9062 = F5BFE5A602F984FA01DC9062; + F5BFE5A702F984FA01DC9062 = F5BFE5A702F984FA01DC9062; + F5BFE5A802F984FA01DC9062 = F5BFE5A802F984FA01DC9062; + F5BFE5AA02F984FA01DC9062 = F5BFE5AA02F984FA01DC9062; + F5BFE5AB02F984FA01DC9062 = F5BFE5AB02F984FA01DC9062; + F5BFE5AC02F984FA01DC9062 = F5BFE5AC02F984FA01DC9062; + F5BFE5AD02F984FA01DC9062 = F5BFE5AD02F984FA01DC9062; + F5BFE5AE02F984FA01DC9062 = F5BFE5AE02F984FA01DC9062; + F5BFE5AF02F984FA01DC9062 = F5BFE5AF02F984FA01DC9062; + F5BFE5B002F984FA01DC9062 = F5BFE5B002F984FA01DC9062; + F5BFE5B202F984FA01DC9062 = F5BFE5B202F984FA01DC9062; + F5BFE5B302F984FA01DC9062 = F5BFE5B302F984FA01DC9062; + F5BFE5B402F984FA01DC9062 = F5BFE5B402F984FA01DC9062; + F5BFE5B502F984FA01DC9062 = F5BFE5B502F984FA01DC9062; + F5BFE5B702F984FA01DC9062 = F5BFE5B702F984FA01DC9062; + F5BFE5B802F984FA01DC9062 = F5BFE5B802F984FA01DC9062; + F5BFE5B902F984FA01DC9062 = F5BFE5B902F984FA01DC9062; + F5BFE5BB02F984FA01DC9062 = F5BFE5BB02F984FA01DC9062; + F5BFE5BC02F984FA01DC9062 = F5BFE5BC02F984FA01DC9062; + F5BFE5BD02F984FA01DC9062 = F5BFE5BD02F984FA01DC9062; + F5BFE5BE02F984FA01DC9062 = F5BFE5BE02F984FA01DC9062; + F5BFE5BF02F984FA01DC9062 = F5BFE5BF02F984FA01DC9062; + F5BFE5C002F984FA01DC9062 = F5BFE5C002F984FA01DC9062; + F5BFE5C102F984FA01DC9062 = F5BFE5C102F984FA01DC9062; + F5BFE5C402F984FA01DC9062 = F5BFE5C402F984FA01DC9062; + }; + projectwideBuildSettings = { + OBJROOT = "/Volumes/TheCloset/jingham/tcl-tk/source/tcl-merge/Objects"; + SYMROOT = "/Volumes/TheCloset/jingham/tcl-tk/source/tcl-merge/Products"; + }; + wantsIndex = 1; + wantsSCM = -1; + }; + F53755DF016C38D201DC9062 = { + activeExec = 0; + }; + F53756A0016C4DD401DC9062 = { + activeExec = 0; + executables = ( + F53756AB016C4DD401DC9062, + ); + }; + F53756AB016C4DD401DC9062 = { + activeArgIndex = 2147483647; + argumentStrings = ( + ); + debuggerPlugin = GDBDebugging; + dylibVariantSuffix = ""; + enableDebugStr = 1; + environmentEntries = ( + ); + isa = PBXExecutable; + name = "Wish Shell"; + shlibInfoDictList = ( + ); + sourceDirectories = ( + ); + }; + F55BC4B602B2DFB901DC9062 = { + fileReference = F5375580016C389901DC9062; + isa = PBXFileBreakpoint; + lineNumber = 201; + state = 2; + }; + F55BC4B902B2E09101DC9062 = { + fRef = F5375553016C376E01DC9062; + isa = PBXTextBookmark; + name = "tkMacOSXEvent.c: 242"; + rLen = 0; + rLoc = 6185; + rType = 0; + vrLen = 1438; + vrLoc = 5937; + }; + F55BC4BA02B2E09101DC9062 = { + fRef = F55BC46A02B2D3F301DC9062; + isa = PBXTextBookmark; + name = "panedwindow.tcl: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1395; + vrLoc = 0; + }; + F55BC4BD02B2E09101DC9062 = { + bstl = F537552C016C352C01DC9062; + isa = PBXBuildStyleBookmark; + }; + F55BC4BF02B2E09101DC9062 = { + fRef = F5375553016C376E01DC9062; + isa = PBXTextBookmark; + name = "tkMacOSXEvent.c: 242"; + rLen = 0; + rLoc = 6185; + rType = 0; + vrLen = 1438; + vrLoc = 5937; + }; + F55BC4C002B2E09101DC9062 = { + isa = PBXTargetBookmark; + trg = F53755DF016C38D201DC9062; + }; + F55BC4C102B2E09101DC9062 = { + fRef = F55BC46A02B2D3F301DC9062; + isa = PBXTextBookmark; + name = "panedwindow.tcl: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1395; + vrLoc = 0; + }; + F55BC4C202B2E09101DC9062 = { + isa = PBXTargetBookmark; + trg = F53755DF016C38D201DC9062; + }; + F55BC4C302B2E09101DC9062 = { + fRef = F55BC46A02B2D3F301DC9062; + isa = PBXTextBookmark; + name = "panedwindow.tcl: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1395; + vrLoc = 0; + }; + F55BC4C402B2E09101DC9062 = { + isa = PBXTargetBookmark; + trg = F53755DF016C38D201DC9062; + }; + F55BC4C702B2E09101DC9062 = { + bstl = F537552C016C352C01DC9062; + isa = PBXBuildStyleBookmark; + }; + F566083B0197283B01DC9062 = { + fileReference = F5375548016C376E01DC9062; + isa = PBXFileBreakpoint; + lineNumber = 214; + state = 2; + }; + F566083C0197823801DC9062 = { + isa = PBXSymbolicBreakpoint; + state = 2; + symbolName = Tcl_CreateObjCommand; + }; + F571FE470179562E01DC9062 = { + fileReference = F5375583016C389901DC9062; + isa = PBXFileBreakpoint; + lineNumber = 1711; + state = 2; + }; + F571FE4A0179695001DC9062 = { + fileReference = F5375558016C376E01DC9062; + isa = PBXFileBreakpoint; + lineNumber = 175; + state = 2; + }; + F571FE4C01796B1101DC9062 = { + fileReference = F5375558016C376E01DC9062; + isa = PBXFileBreakpoint; + lineNumber = 172; + state = 2; + }; + F571FE4D01796CAF01DC9062 = { + fileReference = F5375558016C376E01DC9062; + isa = PBXFileBreakpoint; + lineNumber = 229; + state = 2; + }; + F571FE4E01796F9201DC9062 = { + fileReference = F53755C8016C389901DC9062; + isa = PBXFileBreakpoint; + lineNumber = 408; + state = 2; + }; + F571FE4F0179702301DC9062 = { + fileReference = F537559A016C389901DC9062; + isa = PBXFileBreakpoint; + lineNumber = 444; + state = 2; + }; + F571FE500179702301DC9062 = { + fileReference = F537559A016C389901DC9062; + isa = PBXFileBreakpoint; + lineNumber = 469; + state = 2; + }; + F583DC0E018D092D01DC9062 = { + fileReference = F5375551016C376E01DC9062; + isa = PBXFileBreakpoint; + lineNumber = 531; + state = 2; + }; + F583DC0F018D0CB501DC9062 = { + fileReference = F5375551016C376E01DC9062; + isa = PBXFileBreakpoint; + lineNumber = 547; + state = 2; + }; + F583DC13018D2B4A01DC9062 = { + fileReference = F5375551016C376E01DC9062; + isa = PBXFileBreakpoint; + lineNumber = 1478; + state = 2; + }; + F58907BE018DCE8F01DC9062 = { + fileReference = F5375548016C376E01DC9062; + isa = PBXFileBreakpoint; + lineNumber = 196; + state = 2; + }; + F58907C5018DD1C301DC9062 = { + fileReference = F5375551016C376E01DC9062; + isa = PBXFileBreakpoint; + lineNumber = 502; + state = 2; + }; + F5978FD602B3190701DC9062 = { + fileReference = F5375580016C389901DC9062; + isa = PBXFileBreakpoint; + lineNumber = 224; + state = 2; + }; + F5A439C0029B609C01DC9064 = { + fileReference = F5375548016C376E01DC9062; + isa = PBXFileBreakpoint; + lineNumber = 74; + state = 1; + }; + F5A439C2029B60ED01DC9064 = { + fileReference = F5375548016C376E01DC9062; + isa = PBXFileBreakpoint; + lineNumber = 155; + state = 1; + }; + F5A439CA029B620901DC9064 = { + fileReference = F5375548016C376E01DC9062; + isa = PBXFileBreakpoint; + lineNumber = 306; + state = 1; + }; + F5A439D1029B6B5501DC9064 = { + fRef = F5A439F3029B6B5601DC9064; + isa = PBXTextBookmark; + name = "CarbonEvents.h: 4483"; + rLen = 19; + rLoc = 173576; + rType = 0; + vrLen = 804; + vrLoc = 173125; + }; + F5A439D2029B6B5501DC9064 = { + fRef = F5375548016C376E01DC9062; + isa = PBXTextBookmark; + name = "tkMacOSXAppInit.c: Tcl_AppInit"; + rLen = 0; + rLoc = 9908; + rType = 0; + vrLen = 1370; + vrLoc = 8362; + }; + F5A439D3029B6B5501DC9064 = { + fRef = F5A439F4029B6B5601DC9064; + isa = PBXTextBookmark; + name = "MacWindows.h: 1410"; + rLen = 105; + rLoc = 57285; + rType = 0; + vrLen = 1155; + vrLoc = 56795; + }; + F5A439D4029B6B5501DC9064 = { + fRef = F5A439F5029B6B5601DC9064; + isa = PBXBookmark; + }; + F5A439D5029B6B5501DC9064 = { + fRef = F5A439F6029B6B5601DC9064; + isa = PBXBookmark; + }; + F5A439D6029B6B5501DC9064 = { + fRef = F5A439F7029B6B5601DC9064; + isa = PBXBookmark; + }; + F5A439D7029B6B5501DC9064 = { + fRef = F5A439F8029B6B5601DC9064; + isa = PBXBookmark; + }; + F5A439DA029B6B5501DC9064 = { + fRef = F5375553016C376E01DC9062; + isa = PBXTextBookmark; + name = "tkMacOSXEvent.c: TkMacOSXProcessEvent"; + rLen = 25; + rLoc = 4656; + rType = 0; + vrLen = 1260; + vrLoc = 4407; + }; + F5A439DB029B6B5501DC9064 = { + fRef = F537555C016C376E01DC9062; + isa = PBXTextBookmark; + name = "tkMacOSXMouseEvent.c: TkMacOSXProcessMouseEvent"; + rLen = 0; + rLoc = 6037; + rType = 0; + vrLen = 1438; + vrLoc = 5075; + }; + F5A439DE029B6B5501DC9064 = { + fRef = F5375553016C376E01DC9062; + isa = PBXTextBookmark; + name = "tkMacOSXEvent.c: ReceiveAndProcessEvent"; + rLen = 0; + rLoc = 7098; + rType = 0; + vrLen = 1455; + vrLoc = 5920; + }; + F5A439DF029B6B5501DC9064 = { + fRef = F5375548016C376E01DC9062; + isa = PBXTextBookmark; + name = "tkMacOSXAppInit.c: Tcl_AppInit"; + rLen = 0; + rLoc = 9908; + rType = 0; + vrLen = 673; + vrLoc = 7806; + }; + F5A439E0029B6B5501DC9064 = { + fRef = F5375567016C376E01DC9062; + isa = PBXTextBookmark; + name = "tkMacOSXWm.c: TkMacOSXMakeRealWindowExist"; + rLen = 15; + rLoc = 148454; + rType = 0; + vrLen = 695; + vrLoc = 112860; + }; + F5A439E1029B6B5501DC9064 = { + fRef = F5A439FB029B6B5601DC9064; + isa = PBXTextBookmark; + name = "MacWindows.h: 1410"; + rLen = 0; + rLoc = 57304; + rType = 0; + vrLen = 659; + vrLoc = 56953; + }; + F5A439E2029B6B5501DC9064 = { + fRef = F5375548016C376E01DC9062; + isa = PBXTextBookmark; + name = "tkMacOSXAppInit.c: Tcl_AppInit"; + rLen = 0; + rLoc = 9908; + rType = 0; + vrLen = 1370; + vrLoc = 8362; + }; + F5A439E3029B6B5501DC9064 = { + fRef = F5A439EF029B6B5601DC9064; + isa = PBXTextBookmark; + name = "MacWindows.h: 1410"; + rLen = 105; + rLoc = 57285; + rType = 0; + vrLen = 1155; + vrLoc = 56795; + }; + F5A439E4029B6B5501DC9064 = { + fRef = F5A439F1029B6B5601DC9064; + isa = PBXBookmark; + }; + F5A439E5029B6B5501DC9064 = { + fRef = F5A439FD029B6B5601DC9064; + isa = PBXBookmark; + }; + F5A439E6029B6B5501DC9064 = { + fRef = F5A439FE029B6B5601DC9064; + isa = PBXBookmark; + }; + F5A439E7029B6B5501DC9064 = { + fRef = F5A439EE029B6B5601DC9064; + isa = PBXBookmark; + }; + F5A439E8029B6B5501DC9064 = { + fRef = F5A439F2029B6B5601DC9064; + isa = PBXBookmark; + }; + F5A439EE029B6B5601DC9064 = { + isa = PBXFileReference; + name = Carbon.html; + path = /Developer/Documentation/Carbon/Carbon.html; + refType = 0; + }; + F5A439EF029B6B5601DC9064 = { + isa = PBXFileReference; + name = MacWindows.h; + path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/MacWindows.h; + refType = 0; + }; + F5A439F1029B6B5601DC9064 = { + isa = PBXFileReference; + name = Carbon.html; + path = /Developer/Documentation/Carbon/Carbon.html; + refType = 0; + }; + F5A439F2029B6B5601DC9064 = { + isa = PBXFileReference; + name = carboneventmanager.html; + path = /Developer/Documentation/Carbon/oss/CarbonEventManager/carboneventmanager.html; + refType = 0; + }; + F5A439F3029B6B5601DC9064 = { + isa = PBXFileReference; + name = CarbonEvents.h; + path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/CarbonEvents.h; + refType = 0; + }; + F5A439F4029B6B5601DC9064 = { + isa = PBXFileReference; + name = MacWindows.h; + path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/MacWindows.h; + refType = 0; + }; + F5A439F5029B6B5601DC9064 = { + isa = PBXFileReference; + name = windowmanager.html; + path = /Developer/Documentation/Carbon/HumanInterfaceToolbox/WindowManager/windowmanager.html; + refType = 0; + }; + F5A439F6029B6B5601DC9064 = { + isa = PBXFileReference; + name = index.html; + path = /Developer/Documentation/Carbon/HumanInterfaceToolbox/WindowManager/Window_Manager/index.html; + refType = 0; + }; + F5A439F7029B6B5601DC9064 = { + isa = PBXFileReference; + name = Carbon.html; + path = /Developer/Documentation/Carbon/Carbon.html; + refType = 0; + }; + F5A439F8029B6B5601DC9064 = { + isa = PBXFileReference; + name = carboneventmanager.html; + path = /Developer/Documentation/Carbon/oss/CarbonEventManager/carboneventmanager.html; + refType = 0; + }; + F5A439FB029B6B5601DC9064 = { + isa = PBXFileReference; + name = MacWindows.h; + path = /System/Library/Frameworks/Carbon.framework/Versions/A/Frameworks/HIToolbox.framework/Versions/A/Headers/MacWindows.h; + refType = 0; + }; + F5A439FD029B6B5601DC9064 = { + isa = PBXFileReference; + name = windowmanager.html; + path = /Developer/Documentation/Carbon/HumanInterfaceToolbox/WindowManager/windowmanager.html; + refType = 0; + }; + F5A439FE029B6B5601DC9064 = { + isa = PBXFileReference; + name = index.html; + path = /Developer/Documentation/Carbon/HumanInterfaceToolbox/WindowManager/Window_Manager/index.html; + refType = 0; + }; + F5A5146F01D05DC201DC9062 = { + fileReference = F5375550016C376E01DC9062; + isa = PBXFileBreakpoint; + lineNumber = 651; + state = 1; + }; + F5A5147001D0758C01DC9062 = { + fileReference = F5375550016C376E01DC9062; + isa = PBXFileBreakpoint; + lineNumber = 838; + state = 1; + }; + F5A852D6020F6C6C01DC9062 = { + fileReference = F5375550016C376E01DC9062; + isa = PBXFileBreakpoint; + lineNumber = 277; + state = 1; + }; + F5B2CDC10175829501DC9062 = { + fileReference = F5375583016C389901DC9062; + isa = PBXFileBreakpoint; + lineNumber = 2584; + state = 2; + }; + F5BE671E029B6FEE01DC9064 = { + fRef = F5BE6723029B6FEE01DC9064; + isa = PBXBookmark; + }; + F5BE671F029B6FEE01DC9064 = { + fRef = F5BE6722029B6FEE01DC9064; + isa = PBXBookmark; + }; + F5BE6722029B6FEE01DC9064 = { + isa = PBXFileReference; + name = index.html; + path = /Developer/Documentation/Carbon/oss/CarbonEventManager/Carbon_Event_Manager_Ref/index.html; + refType = 0; + }; + F5BE6723029B6FEE01DC9064 = { + isa = PBXFileReference; + name = index.html; + path = /Developer/Documentation/Carbon/oss/CarbonEventManager/Carbon_Event_Manager_Ref/index.html; + refType = 0; + }; + F5BFE59402F984FA01DC9062 = { + isa = PBXTargetBookmark; + trg = F53755DF016C38D201DC9062; + }; + F5BFE59502F984FA01DC9062 = { + fRef = F53755BC016C389901DC9062; + isa = PBXTextBookmark; + name = "tkTest.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1168; + vrLoc = 0; + }; + F5BFE59602F984FA01DC9062 = { + fRef = F5BFE58C02F8C41501DC9062; + isa = PBXTextBookmark; + name = "tkUndo.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 723; + vrLoc = 0; + }; + F5BFE59702F984FA01DC9062 = { + fRef = F5BFE58F02F8C45B01DC9062; + isa = PBXTextBookmark; + name = "tkUndo.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1028; + vrLoc = 0; + }; + F5BFE59802F984FA01DC9062 = { + fRef = F5375575016C37A601DC9062; + isa = PBXTextBookmark; + name = "tkIntDecls.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 959; + vrLoc = 52384; + }; + F5BFE59902F984FA01DC9062 = { + fRef = F537556A016C37A601DC9062; + isa = PBXTextBookmark; + name = "ks_names.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 963; + vrLoc = 0; + }; + F5BFE59B02F984FA01DC9062 = { + fRef = F537559F016C389901DC9062; + isa = PBXTextBookmark; + name = "tkGet.c: Tk_GetUid"; + rLen = 50; + rLoc = 13445; + rType = 0; + vrLen = 1360; + vrLoc = 12671; + }; + F5BFE59C02F984FA01DC9062 = { + fRef = F5375545016C376E01DC9062; + isa = PBXTextBookmark; + name = "tkMacOSXWm.h: 104"; + rLen = 6; + rLoc = 4294; + rType = 0; + vrLen = 1558; + vrLoc = 8742; + }; + F5BFE59D02F984FA01DC9062 = { + fRef = F537556B016C37A601DC9062; + isa = PBXTextBookmark; + name = "tk.h: 1606"; + rLen = 0; + rLoc = 56812; + rType = 0; + vrLen = 897; + vrLoc = 55983; + }; + F5BFE59E02F984FA01DC9062 = { + exec = F53756AB016C4DD401DC9062; + isa = PBXExecutableBookmark; + }; + F5BFE59F02F984FA01DC9062 = { + fRef = F5BFE5E102F984FA01DC9062; + isa = PBXBookmark; + }; + F5BFE5A002F984FA01DC9062 = { + fRef = F5BFE5DA02F984FA01DC9062; + isa = PBXBookmark; + }; + F5BFE5A102F984FA01DC9062 = { + fRef = F5BFE5DC02F984FA01DC9062; + isa = PBXBookmark; + }; + F5BFE5A202F984FA01DC9062 = { + fRef = F5BFE5DB02F984FA01DC9062; + isa = PBXBookmark; + }; + F5BFE5A402F984FA01DC9062 = { + fRef = F5BFE5DD02F984FA01DC9062; + isa = PBXBookmark; + }; + F5BFE5A502F984FA01DC9062 = { + fRef = F5375567016C376E01DC9062; + isa = PBXTextBookmark; + name = "tkMacOSXWm.c: TkUnsupported1Cmd"; + rLen = 15; + rLoc = 148454; + rType = 0; + vrLen = 1386; + vrLoc = 112609; + }; + F5BFE5A602F984FA01DC9062 = { + fRef = F5375568016C376E01DC9062; + isa = PBXTextBookmark; + name = "tkMacOSXXStubs.c: TkpCloseDisplay"; + rLen = 0; + rLoc = 5311; + rType = 0; + vrLen = 437; + vrLoc = 4370; + }; + F5BFE5A702F984FA01DC9062 = { + fRef = F53755C8016C389901DC9062; + isa = PBXTextBookmark; + name = "tkWindow.c: TkCloseDisplay"; + rLen = 0; + rLoc = 9153; + rType = 0; + vrLen = 453; + vrLoc = 8833; + }; + F5BFE5A802F984FA01DC9062 = { + fRef = F537555C016C376E01DC9062; + isa = PBXTextBookmark; + name = "tkMacOSXMouseEvent.c: TkMacOSXProcessMouseEvent"; + rLen = 0; + rLoc = 6187; + rType = 0; + vrLen = 742; + vrLoc = 11312; + }; + F5BFE5AA02F984FA01DC9062 = { + isa = PBXTargetBookmark; + trg = F53755DF016C38D201DC9062; + }; + F5BFE5AB02F984FA01DC9062 = { + fRef = F53755BC016C389901DC9062; + isa = PBXTextBookmark; + name = "tkTest.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1168; + vrLoc = 0; + }; + F5BFE5AC02F984FA01DC9062 = { + fRef = F5BFE58C02F8C41501DC9062; + isa = PBXTextBookmark; + name = "tkUndo.c: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 723; + vrLoc = 0; + }; + F5BFE5AD02F984FA01DC9062 = { + fRef = F5BFE58F02F8C45B01DC9062; + isa = PBXTextBookmark; + name = "tkUndo.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 1028; + vrLoc = 0; + }; + F5BFE5AE02F984FA01DC9062 = { + fRef = F5375575016C37A601DC9062; + isa = PBXTextBookmark; + name = "tkIntDecls.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 959; + vrLoc = 52384; + }; + F5BFE5AF02F984FA01DC9062 = { + fRef = F537556A016C37A601DC9062; + isa = PBXTextBookmark; + name = "ks_names.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 963; + vrLoc = 0; + }; + F5BFE5B002F984FA01DC9062 = { + fRef = F537556B016C37A601DC9062; + isa = PBXTextBookmark; + name = "tk.h: 1"; + rLen = 0; + rLoc = 0; + rType = 0; + vrLen = 882; + vrLoc = 55769; + }; + F5BFE5B202F984FA01DC9062 = { + fRef = F537559F016C389901DC9062; + isa = PBXTextBookmark; + name = "tkGet.c: Tk_GetUid"; + rLen = 50; + rLoc = 13445; + rType = 0; + vrLen = 1360; + vrLoc = 12671; + }; + F5BFE5B302F984FA01DC9062 = { + fRef = F5375545016C376E01DC9062; + isa = PBXTextBookmark; + name = "tkMacOSXWm.h: 104"; + rLen = 6; + rLoc = 4294; + rType = 0; + vrLen = 1558; + vrLoc = 8742; + }; + F5BFE5B402F984FA01DC9062 = { + fRef = F537556B016C37A601DC9062; + isa = PBXTextBookmark; + name = "tk.h: 1606"; + rLen = 0; + rLoc = 56812; + rType = 0; + vrLen = 897; + vrLoc = 55983; + }; + F5BFE5B502F984FA01DC9062 = { + exec = F53756AB016C4DD401DC9062; + isa = PBXExecutableBookmark; + }; + F5BFE5B702F984FA01DC9062 = { + fRef = F5BFE5DF02F984FA01DC9062; + isa = PBXBookmark; + }; + F5BFE5B802F984FA01DC9062 = { + fRef = F5BFE5D902F984FA01DC9062; + isa = PBXBookmark; + }; + F5BFE5B902F984FA01DC9062 = { + fRef = F5BFE5E502F984FA01DC9062; + isa = PBXBookmark; + }; + F5BFE5BB02F984FA01DC9062 = { + fRef = F5BFE5D802F984FA01DC9062; + isa = PBXBookmark; + }; + F5BFE5BC02F984FA01DC9062 = { + fRef = F5375567016C376E01DC9062; + isa = PBXTextBookmark; + name = "tkMacOSXWm.c: TkUnsupported1Cmd"; + rLen = 15; + rLoc = 148454; + rType = 0; + vrLen = 1386; + vrLoc = 112609; + }; + F5BFE5BD02F984FA01DC9062 = { + fRef = F5375568016C376E01DC9062; + isa = PBXTextBookmark; + name = "tkMacOSXXStubs.c: 92"; + rLen = 14; + rLoc = 2403; + rType = 0; + vrLen = 1501; + vrLoc = 2945; + }; + F5BFE5BE02F984FA01DC9062 = { + fRef = F53755C8016C389901DC9062; + isa = PBXTextBookmark; + name = "tkWindow.c: DeleteWindowsExitProc"; + rLen = 0; + rLoc = 79080; + rType = 0; + vrLen = 1549; + vrLoc = 78212; + }; + F5BFE5BF02F984FA01DC9062 = { + fRef = F5375568016C376E01DC9062; + isa = PBXTextBookmark; + name = "tkMacOSXXStubs.c: TkpCloseDisplay"; + rLen = 0; + rLoc = 5311; + rType = 0; + vrLen = 437; + vrLoc = 4370; + }; + F5BFE5C002F984FA01DC9062 = { + fRef = F53755C8016C389901DC9062; + isa = PBXTextBookmark; + name = "tkWindow.c: TkCloseDisplay"; + rLen = 0; + rLoc = 9153; + rType = 0; + vrLen = 453; + vrLoc = 8833; + }; + F5BFE5C102F984FA01DC9062 = { + fRef = F537555C016C376E01DC9062; + isa = PBXTextBookmark; + name = "tkMacOSXMouseEvent.c: TkMacOSXProcessMouseEvent"; + rLen = 0; + rLoc = 6187; + rType = 0; + vrLen = 742; + vrLoc = 11312; + }; + F5BFE5C402F984FA01DC9062 = { + fRef = F5375568016C376E01DC9062; + isa = PBXTextBookmark; + name = "tkMacOSXXStubs.c: TkpCloseDisplay"; + rLen = 0; + rLoc = 5311; + rType = 0; + vrLen = 500; + vrLoc = 4894; + }; + F5BFE5D802F984FA01DC9062 = { + isa = PBXFileReference; + name = README.html; + path = /Developer/Documentation/Help/README/README.html; + refType = 0; + }; + F5BFE5D902F984FA01DC9062 = { + isa = PBXFileReference; + name = index.html; + path = /Developer/Documentation/ReleaseNotes/index.html; + refType = 0; + }; + F5BFE5DA02F984FA01DC9062 = { + isa = PBXFileReference; + name = devessentials.html; + path = /Developer/Documentation/Essentials/devessentials.html; + refType = 0; + }; + F5BFE5DB02F984FA01DC9062 = { + isa = PBXFileReference; + name = index.html; + path = /Developer/Documentation/ReleaseNotes/index.html; + refType = 0; + }; + F5BFE5DC02F984FA01DC9062 = { + isa = PBXFileReference; + name = MallocOptions.html; + path = /Developer/Documentation/ReleaseNotes/MallocOptions.html; + refType = 0; + }; + F5BFE5DD02F984FA01DC9062 = { + isa = PBXFileReference; + name = README.html; + path = /Developer/Documentation/Help/README/README.html; + refType = 0; + }; + F5BFE5DF02F984FA01DC9062 = { + isa = PBXFileReference; + name = devessentials.html; + path = /Developer/Documentation/Essentials/devessentials.html; + refType = 0; + }; + F5BFE5E102F984FA01DC9062 = { + isa = PBXFileReference; + name = devtools.html; + path = /Developer/Documentation/DeveloperTools/devtools.html; + refType = 0; + }; + F5BFE5E502F984FA01DC9062 = { + isa = PBXFileReference; + name = README.html; + path = /Developer/Documentation/Help/README/README.html; + refType = 0; + }; +} diff --git a/macosx/Wish.pbproj/project.pbxproj b/macosx/Wish.pbproj/project.pbxproj new file mode 100644 index 0000000..b3a7b98 --- /dev/null +++ b/macosx/Wish.pbproj/project.pbxproj @@ -0,0 +1,3593 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 38; + objects = { + F50D96120196176E01DC9062 = { + isa = PBXFrameworkReference; + name = ApplicationServices.framework; + path = /System/Library/Frameworks/ApplicationServices.framework; + refType = 0; + }; + F50D96130196176E01DC9062 = { + fileRef = F50D96120196176E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F50D96140196176E01DC9062 = { + fileRef = F50D96120196176E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F51D903E0181474301DC9062 = { + fileRef = F5875C7B016FEF1D01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F51D903F018149BD01DC9062 = { + buildActionMask = 2147483647; + dstPath = "Versions/$(FRAMEWORK_VERSION)/Headers/X11"; + dstSubfolderSpec = 1; + files = ( + F51D9040018149FD01DC9062, + F51D9041018149FD01DC9062, + F51D9042018149FD01DC9062, + F51D9043018149FD01DC9062, + F51D9044018149FD01DC9062, + F51D9045018149FD01DC9062, + F51D9046018149FD01DC9062, + F51D9047018149FD01DC9062, + F51D9048018149FD01DC9062, + ); + isa = PBXCopyFilesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F51D9040018149FD01DC9062 = { + fileRef = F53755CE016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F51D9041018149FD01DC9062 = { + fileRef = F53755CF016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F51D9042018149FD01DC9062 = { + fileRef = F53755D0016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F51D9043018149FD01DC9062 = { + fileRef = F53755D1016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F51D9044018149FD01DC9062 = { + fileRef = F53755D2016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F51D9045018149FD01DC9062 = { + fileRef = F53755D3016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F51D9046018149FD01DC9062 = { + fileRef = F53755D4016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F51D9047018149FD01DC9062 = { + fileRef = F53755D5016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F51D9048018149FD01DC9062 = { + fileRef = F53755D6016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F52D38C5031F4259016F146B = { + buildActionMask = 2147483647; + files = ( + ); + generatedFileNames = ( + ); + isa = PBXShellScriptBuildPhase; + neededFileNames = ( + ); + runOnlyForDeploymentPostprocessing = 0; + shellPath = /bin/sh; + shellScript = "if [ \"${BUILD_STYLE}\" = \"Development\" ]; then\n\t# keep copy of debug library around, so that\n\t# Deployment build can be installed on top\n\t# of Development build without overwriting it\n\tcd \"${TARGET_BUILD_DIR}/${PRODUCT_NAME}.${WRAPPER_EXTENSION}/Versions/${FRAMEWORK_VERSION}\"\n\tcp -fp \"${PRODUCT_NAME}\" \"${PRODUCT_NAME}_debug\"\n\n\t# force Deployment build to be relinked next time\n\tif [ -f \"${OBJROOT}/Deployment.build/${PROJECT_NAME}.build/${TARGET_NAME}.build/Objects-normal/LinkFileList\" ]; then\n\t touch -t `date -r \\`expr \\\\\\`date +\"%s\"\\\\\\` + 30\\` +\"%G%m%d%H%M.%S\"` \"${OBJROOT}/Deployment.build/${PROJECT_NAME}.build/${TARGET_NAME}.build/Objects-normal/LinkFileList\"\n\tfi\nelse\n\t# force Development build to be relinked next time\n\tif [ -f \"${OBJROOT}/Development.build/${PROJECT_NAME}.build/${TARGET_NAME}.build/Objects-normal/LinkFileList\" ]; then\n\t touch -t `date -r \\`expr \\\\\\`date +\"%s\"\\\\\\` + 30\\` +\"%G%m%d%H%M.%S\"` \"${OBJROOT}/Development.build/${PROJECT_NAME}.build/${TARGET_NAME}.build/Objects-normal/LinkFileList\"\n\tfi\nfi"; + }; + F537552A016C352C01DC9062 = { + buildStyles = ( + F537552C016C352C01DC9062, + F537552D016C352C01DC9062, + ); + isa = PBXProject; + mainGroup = F537552B016C352C01DC9062; + productRefGroup = F53755DD016C38D201DC9062; + projectDirPath = ""; + targets = ( + F53756A0016C4DD401DC9062, + F53755DF016C38D201DC9062, + F548F8CE0313CEF0016F146B, + ); + }; + F537552B016C352C01DC9062 = { + children = ( + F5C88659017D625C01DC9062, + F5DF07A7016CD03801DC9062, + F5375688016C3F1001DC9062, + F5375531016C376E01DC9062, + F537552E016C376E01DC9062, + F537553C016C376E01DC9062, + F53755C9016C389901DC9062, + F53755CC016C389901DC9062, + F537567C016C3ADB01DC9062, + F53755DD016C38D201DC9062, + ); + isa = PBXGroup; + refType = 4; + }; + F537552C016C352C01DC9062 = { + buildRules = ( + ); + buildSettings = { + TEMP_DIR = "${OBJROOT}/Development.build/$(PROJECT_NAME).build/$(TARGET_NAME).build"; + UNSTRIPPED_PRODUCT = YES; + }; + isa = PBXBuildStyle; + name = Development; + }; + F537552D016C352C01DC9062 = { + buildRules = ( + ); + buildSettings = { + DEBUGGING_SYMBOLS = NO; + OPTIMIZATION_CFLAGS = "-Os"; + TEMP_DIR = "${OBJROOT}/Deployment.build/$(PROJECT_NAME).build/$(TARGET_NAME).build"; + }; + isa = PBXBuildStyle; + name = Deployment; + }; + F537552E016C376E01DC9062 = { + children = ( + F537552F016C376E01DC9062, + F5375530016C376E01DC9062, + ); + isa = PBXGroup; + name = Generic; + refType = 4; + }; + F537552F016C376E01DC9062 = { + children = ( + F5375569016C37A601DC9062, + F537556A016C37A601DC9062, + F537556B016C37A601DC9062, + F537556C016C37A601DC9062, + F537556D016C37A601DC9062, + F537556E016C37A601DC9062, + F537556F016C37A601DC9062, + F5375570016C37A601DC9062, + F5375571016C37A601DC9062, + F5375572016C37A601DC9062, + F5375573016C37A601DC9062, + F5375574016C37A601DC9062, + F5375575016C37A601DC9062, + F5375576016C37A601DC9062, + F5375577016C37A601DC9062, + F5375578016C37A601DC9062, + F5375579016C37A601DC9062, + F537557A016C37A601DC9062, + F537557B016C37A601DC9062, + F537557C016C37A601DC9062, + F537557D016C37A601DC9062, + F537557E016C37A601DC9062, + F537557F016C37A601DC9062, + F5BFE58F02F8C45B01DC9062, + ); + isa = PBXGroup; + name = Headers; + refType = 4; + }; + F5375530016C376E01DC9062 = { + children = ( + F5375580016C389901DC9062, + F5375581016C389901DC9062, + F5375582016C389901DC9062, + F5375583016C389901DC9062, + F5375584016C389901DC9062, + F5375585016C389901DC9062, + F5375586016C389901DC9062, + F5375587016C389901DC9062, + F5375588016C389901DC9062, + F5375589016C389901DC9062, + F537558A016C389901DC9062, + F537558B016C389901DC9062, + F537558C016C389901DC9062, + F537558D016C389901DC9062, + F537558E016C389901DC9062, + F537558F016C389901DC9062, + F5375590016C389901DC9062, + F5375591016C389901DC9062, + F5375592016C389901DC9062, + F5375593016C389901DC9062, + F5375594016C389901DC9062, + F5375595016C389901DC9062, + F5375596016C389901DC9062, + F5375597016C389901DC9062, + F5375598016C389901DC9062, + F5375599016C389901DC9062, + F537559A016C389901DC9062, + F537559B016C389901DC9062, + F537559C016C389901DC9062, + F537559D016C389901DC9062, + F537559E016C389901DC9062, + F537559F016C389901DC9062, + F53755A0016C389901DC9062, + F53755A1016C389901DC9062, + F53755A2016C389901DC9062, + F53755A3016C389901DC9062, + F53755A4016C389901DC9062, + F53755A5016C389901DC9062, + F53755A6016C389901DC9062, + F53755A7016C389901DC9062, + F53755A8016C389901DC9062, + F53755A9016C389901DC9062, + F53755AA016C389901DC9062, + F53755AB016C389901DC9062, + F53755AC016C389901DC9062, + F53755AD016C389901DC9062, + F53755AE016C389901DC9062, + F53755AF016C389901DC9062, + F53755B0016C389901DC9062, + F53755B1016C389901DC9062, + F53755B2016C389901DC9062, + F55BC46802B2D38B01DC9062, + F53755B3016C389901DC9062, + F53755B4016C389901DC9062, + F53755B5016C389901DC9062, + F53755B6016C389901DC9062, + F53755B7016C389901DC9062, + F53755B8016C389901DC9062, + F53755B9016C389901DC9062, + F53755BA016C389901DC9062, + F53755BB016C389901DC9062, + F5BFE58B02F8C41501DC9062, + F53755BC016C389901DC9062, + F53755BD016C389901DC9062, + F53755BE016C389901DC9062, + F53755BF016C389901DC9062, + F53755C0016C389901DC9062, + F53755C1016C389901DC9062, + F53755C2016C389901DC9062, + F53755C3016C389901DC9062, + F53755C4016C389901DC9062, + F53755C5016C389901DC9062, + F5BFE58C02F8C41501DC9062, + F53755C6016C389901DC9062, + F53755C7016C389901DC9062, + F53755C8016C389901DC9062, + ); + isa = PBXGroup; + name = Source; + refType = 4; + }; + F5375531016C376E01DC9062 = { + children = ( + F5375532016C376E01DC9062, + F537553B016C376E01DC9062, + ); + isa = PBXGroup; + name = Resources; + refType = 4; + }; + F5375532016C376E01DC9062 = { + children = ( + F5375533016C376E01DC9062, + F5375534016C376E01DC9062, + F5375535016C376E01DC9062, + F5375536016C376E01DC9062, + F5375538016C376E01DC9062, + F5375539016C376E01DC9062, + F537553A016C376E01DC9062, + ); + isa = PBXGroup; + name = "Resource Manager Resources"; + refType = 4; + }; + F5375533016C376E01DC9062 = { + isa = PBXFileReference; + path = tkAboutDlg.r; + refType = 4; + }; + F5375534016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXApplication.r; + refType = 4; + }; + F5375535016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXCursors.r; + refType = 4; + }; + F5375536016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXLibrary.r; + refType = 4; + }; + F5375538016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXMenu.r; + refType = 4; + }; + F5375539016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXResource.r; + refType = 4; + }; + F537553A016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXXCursors.r; + refType = 4; + }; + F537553B016C376E01DC9062 = { + isa = PBXFileReference; + path = Wish.icns; + refType = 4; + }; + F537553C016C376E01DC9062 = { + children = ( + F537553D016C376E01DC9062, + F5375546016C376E01DC9062, + ); + isa = PBXGroup; + name = "MacOS X"; + refType = 4; + }; + F537553D016C376E01DC9062 = { + children = ( + F537553E016C376E01DC9062, + F537553F016C376E01DC9062, + F5375540016C376E01DC9062, + F5375541016C376E01DC9062, + F5375542016C376E01DC9062, + F5375543016C376E01DC9062, + F5375544016C376E01DC9062, + F5375545016C376E01DC9062, + ); + isa = PBXGroup; + name = Headers; + refType = 4; + }; + F537553E016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSX.h; + refType = 2; + }; + F537553F016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXDebug.h; + refType = 2; + }; + F5375540016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXDefault.h; + refType = 2; + }; + F5375541016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXEvent.h; + refType = 2; + }; + F5375542016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXInt.h; + refType = 2; + }; + F5375543016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXPort.h; + refType = 2; + }; + F5375544016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXUtil.h; + refType = 2; + }; + F5375545016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXWm.h; + refType = 2; + }; + F5375546016C376E01DC9062 = { + children = ( + F5375548016C376E01DC9062, + F5375549016C376E01DC9062, + F537554A016C376E01DC9062, + F537554B016C376E01DC9062, + F537554C016C376E01DC9062, + F537554D016C376E01DC9062, + F537554E016C376E01DC9062, + F537554F016C376E01DC9062, + F5375550016C376E01DC9062, + F5375551016C376E01DC9062, + F5375552016C376E01DC9062, + F5375553016C376E01DC9062, + F5375554016C376E01DC9062, + F5375555016C376E01DC9062, + F5375556016C376E01DC9062, + F5375557016C376E01DC9062, + F5375558016C376E01DC9062, + F5375559016C376E01DC9062, + F537555A016C376E01DC9062, + F537555B016C376E01DC9062, + F537555C016C376E01DC9062, + F537555D016C376E01DC9062, + F537555E016C376E01DC9062, + F5375560016C376E01DC9062, + F5375561016C376E01DC9062, + F5375562016C376E01DC9062, + F5375563016C376E01DC9062, + F5375564016C376E01DC9062, + F5375565016C376E01DC9062, + F5375567016C376E01DC9062, + F5375568016C376E01DC9062, + ); + isa = PBXGroup; + name = Source; + refType = 4; + }; + F5375548016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXAppInit.c; + refType = 4; + }; + F5375549016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXBitmap.c; + refType = 4; + }; + F537554A016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXButton.c; + refType = 4; + }; + F537554B016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXClipboard.c; + refType = 4; + }; + F537554C016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXColor.c; + refType = 4; + }; + F537554D016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXConfig.c; + refType = 4; + }; + F537554E016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXCursor.c; + refType = 4; + }; + F537554F016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXDebug.c; + refType = 4; + }; + F5375550016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXDialog.c; + refType = 4; + }; + F5375551016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXDraw.c; + refType = 4; + }; + F5375552016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXEmbed.c; + refType = 4; + }; + F5375553016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXEvent.c; + refType = 4; + }; + F5375554016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXFont.c; + refType = 4; + }; + F5375555016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXHLEvents.c; + refType = 4; + }; + F5375556016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXInit.c; + refType = 4; + }; + F5375557016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXKeyboard.c; + refType = 4; + }; + F5375558016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXKeyEvent.c; + refType = 4; + }; + F5375559016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXMenu.c; + refType = 4; + }; + F537555A016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXMenubutton.c; + refType = 4; + }; + F537555B016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXMenus.c; + refType = 4; + }; + F537555C016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXMouseEvent.c; + refType = 4; + }; + F537555D016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXNotify.c; + refType = 4; + }; + F537555E016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXRegion.c; + refType = 4; + }; + F5375560016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXScrlbr.c; + refType = 4; + }; + F5375561016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXSend.c; + refType = 4; + }; + F5375562016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXSubwindows.c; + refType = 4; + }; + F5375563016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXTest.c; + refType = 4; + }; + F5375564016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXUtil.c; + refType = 4; + }; + F5375565016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXWindowEvent.c; + refType = 4; + }; + F5375567016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXWm.c; + refType = 4; + }; + F5375568016C376E01DC9062 = { + isa = PBXFileReference; + path = tkMacOSXXStubs.c; + refType = 4; + }; + F5375569016C37A601DC9062 = { + isa = PBXFileReference; + name = default.h; + path = ../generic/default.h; + refType = 2; + }; + F537556A016C37A601DC9062 = { + isa = PBXFileReference; + name = ks_names.h; + path = ../generic/ks_names.h; + refType = 2; + }; + F537556B016C37A601DC9062 = { + isa = PBXFileReference; + name = tk.h; + path = ../generic/tk.h; + refType = 2; + }; + F537556C016C37A601DC9062 = { + isa = PBXFileReference; + name = tk3d.h; + path = ../generic/tk3d.h; + refType = 2; + }; + F537556D016C37A601DC9062 = { + isa = PBXFileReference; + name = tkButton.h; + path = ../generic/tkButton.h; + refType = 2; + }; + F537556E016C37A601DC9062 = { + isa = PBXFileReference; + name = tkCanvas.h; + path = ../generic/tkCanvas.h; + refType = 2; + }; + F537556F016C37A601DC9062 = { + isa = PBXFileReference; + name = tkColor.h; + path = ../generic/tkColor.h; + refType = 2; + }; + F5375570016C37A601DC9062 = { + isa = PBXFileReference; + name = tkDecls.h; + path = ../generic/tkDecls.h; + refType = 2; + }; + F5375571016C37A601DC9062 = { + isa = PBXFileReference; + name = tkFileFilter.h; + path = ../generic/tkFileFilter.h; + refType = 2; + }; + F5375572016C37A601DC9062 = { + isa = PBXFileReference; + name = tkFont.h; + path = ../generic/tkFont.h; + refType = 2; + }; + F5375573016C37A601DC9062 = { + isa = PBXFileReference; + name = tkInitScript.h; + path = ../generic/tkInitScript.h; + refType = 2; + }; + F5375574016C37A601DC9062 = { + isa = PBXFileReference; + name = tkInt.h; + path = ../generic/tkInt.h; + refType = 2; + }; + F5375575016C37A601DC9062 = { + isa = PBXFileReference; + name = tkIntDecls.h; + path = ../generic/tkIntDecls.h; + refType = 2; + }; + F5375576016C37A601DC9062 = { + isa = PBXFileReference; + name = tkIntPlatDecls.h; + path = ../generic/tkIntPlatDecls.h; + refType = 2; + }; + F5375577016C37A601DC9062 = { + isa = PBXFileReference; + name = tkIntXlibDecls.h; + path = ../generic/tkIntXlibDecls.h; + refType = 2; + }; + F5375578016C37A601DC9062 = { + isa = PBXFileReference; + name = tkMenu.h; + path = ../generic/tkMenu.h; + refType = 2; + }; + F5375579016C37A601DC9062 = { + isa = PBXFileReference; + name = tkMenubutton.h; + path = ../generic/tkMenubutton.h; + refType = 2; + }; + F537557A016C37A601DC9062 = { + isa = PBXFileReference; + name = tkPlatDecls.h; + path = ../generic/tkPlatDecls.h; + refType = 2; + }; + F537557B016C37A601DC9062 = { + isa = PBXFileReference; + name = tkPort.h; + path = ../generic/tkPort.h; + refType = 2; + }; + F537557C016C37A601DC9062 = { + isa = PBXFileReference; + name = tkScale.h; + path = ../generic/tkScale.h; + refType = 2; + }; + F537557D016C37A601DC9062 = { + isa = PBXFileReference; + name = tkScrollbar.h; + path = ../generic/tkScrollbar.h; + refType = 2; + }; + F537557E016C37A601DC9062 = { + isa = PBXFileReference; + name = tkSelect.h; + path = ../generic/tkSelect.h; + refType = 2; + }; + F537557F016C37A601DC9062 = { + isa = PBXFileReference; + name = tkText.h; + path = ../generic/tkText.h; + refType = 2; + }; + F5375580016C389901DC9062 = { + isa = PBXFileReference; + name = tk3d.c; + path = ../generic/tk3d.c; + refType = 2; + }; + F5375581016C389901DC9062 = { + isa = PBXFileReference; + name = tkArgv.c; + path = ../generic/tkArgv.c; + refType = 2; + }; + F5375582016C389901DC9062 = { + isa = PBXFileReference; + name = tkAtom.c; + path = ../generic/tkAtom.c; + refType = 2; + }; + F5375583016C389901DC9062 = { + isa = PBXFileReference; + name = tkBind.c; + path = ../generic/tkBind.c; + refType = 2; + }; + F5375584016C389901DC9062 = { + isa = PBXFileReference; + name = tkBitmap.c; + path = ../generic/tkBitmap.c; + refType = 2; + }; + F5375585016C389901DC9062 = { + isa = PBXFileReference; + name = tkButton.c; + path = ../generic/tkButton.c; + refType = 2; + }; + F5375586016C389901DC9062 = { + isa = PBXFileReference; + name = tkCanvArc.c; + path = ../generic/tkCanvArc.c; + refType = 2; + }; + F5375587016C389901DC9062 = { + isa = PBXFileReference; + name = tkCanvas.c; + path = ../generic/tkCanvas.c; + refType = 2; + }; + F5375588016C389901DC9062 = { + isa = PBXFileReference; + name = tkCanvBmap.c; + path = ../generic/tkCanvBmap.c; + refType = 2; + }; + F5375589016C389901DC9062 = { + isa = PBXFileReference; + name = tkCanvImg.c; + path = ../generic/tkCanvImg.c; + refType = 2; + }; + F537558A016C389901DC9062 = { + isa = PBXFileReference; + name = tkCanvLine.c; + path = ../generic/tkCanvLine.c; + refType = 2; + }; + F537558B016C389901DC9062 = { + isa = PBXFileReference; + name = tkCanvPoly.c; + path = ../generic/tkCanvPoly.c; + refType = 2; + }; + F537558C016C389901DC9062 = { + isa = PBXFileReference; + name = tkCanvPs.c; + path = ../generic/tkCanvPs.c; + refType = 2; + }; + F537558D016C389901DC9062 = { + isa = PBXFileReference; + name = tkCanvText.c; + path = ../generic/tkCanvText.c; + refType = 2; + }; + F537558E016C389901DC9062 = { + isa = PBXFileReference; + name = tkCanvUtil.c; + path = ../generic/tkCanvUtil.c; + refType = 2; + }; + F537558F016C389901DC9062 = { + isa = PBXFileReference; + name = tkCanvWind.c; + path = ../generic/tkCanvWind.c; + refType = 2; + }; + F5375590016C389901DC9062 = { + isa = PBXFileReference; + name = tkClipboard.c; + path = ../generic/tkClipboard.c; + refType = 2; + }; + F5375591016C389901DC9062 = { + isa = PBXFileReference; + name = tkCmds.c; + path = ../generic/tkCmds.c; + refType = 2; + }; + F5375592016C389901DC9062 = { + isa = PBXFileReference; + name = tkColor.c; + path = ../generic/tkColor.c; + refType = 2; + }; + F5375593016C389901DC9062 = { + isa = PBXFileReference; + name = tkConfig.c; + path = ../generic/tkConfig.c; + refType = 2; + }; + F5375594016C389901DC9062 = { + isa = PBXFileReference; + name = tkConsole.c; + path = ../generic/tkConsole.c; + refType = 2; + }; + F5375595016C389901DC9062 = { + isa = PBXFileReference; + name = tkCursor.c; + path = ../generic/tkCursor.c; + refType = 2; + }; + F5375596016C389901DC9062 = { + isa = PBXFileReference; + name = tkEntry.c; + path = ../generic/tkEntry.c; + refType = 2; + }; + F5375597016C389901DC9062 = { + isa = PBXFileReference; + name = tkError.c; + path = ../generic/tkError.c; + refType = 2; + }; + F5375598016C389901DC9062 = { + isa = PBXFileReference; + name = tkEvent.c; + path = ../generic/tkEvent.c; + refType = 2; + }; + F5375599016C389901DC9062 = { + isa = PBXFileReference; + name = tkFileFilter.c; + path = ../generic/tkFileFilter.c; + refType = 2; + }; + F537559A016C389901DC9062 = { + isa = PBXFileReference; + name = tkFocus.c; + path = ../generic/tkFocus.c; + refType = 2; + }; + F537559B016C389901DC9062 = { + isa = PBXFileReference; + name = tkFont.c; + path = ../generic/tkFont.c; + refType = 2; + }; + F537559C016C389901DC9062 = { + isa = PBXFileReference; + name = tkFrame.c; + path = ../generic/tkFrame.c; + refType = 2; + }; + F537559D016C389901DC9062 = { + isa = PBXFileReference; + name = tkGC.c; + path = ../generic/tkGC.c; + refType = 2; + }; + F537559E016C389901DC9062 = { + isa = PBXFileReference; + name = tkGeometry.c; + path = ../generic/tkGeometry.c; + refType = 2; + }; + F537559F016C389901DC9062 = { + isa = PBXFileReference; + name = tkGet.c; + path = ../generic/tkGet.c; + refType = 2; + }; + F53755A0016C389901DC9062 = { + isa = PBXFileReference; + name = tkGrab.c; + path = ../generic/tkGrab.c; + refType = 2; + }; + F53755A1016C389901DC9062 = { + isa = PBXFileReference; + name = tkGrid.c; + path = ../generic/tkGrid.c; + refType = 2; + }; + F53755A2016C389901DC9062 = { + isa = PBXFileReference; + name = tkImage.c; + path = ../generic/tkImage.c; + refType = 2; + }; + F53755A3016C389901DC9062 = { + isa = PBXFileReference; + name = tkImgBmap.c; + path = ../generic/tkImgBmap.c; + refType = 2; + }; + F53755A4016C389901DC9062 = { + isa = PBXFileReference; + name = tkImgGIF.c; + path = ../generic/tkImgGIF.c; + refType = 2; + }; + F53755A5016C389901DC9062 = { + isa = PBXFileReference; + name = tkImgPhoto.c; + path = ../generic/tkImgPhoto.c; + refType = 2; + }; + F53755A6016C389901DC9062 = { + isa = PBXFileReference; + name = tkImgPPM.c; + path = ../generic/tkImgPPM.c; + refType = 2; + }; + F53755A7016C389901DC9062 = { + isa = PBXFileReference; + name = tkImgUtil.c; + path = ../generic/tkImgUtil.c; + refType = 2; + }; + F53755A8016C389901DC9062 = { + isa = PBXFileReference; + name = tkListbox.c; + path = ../generic/tkListbox.c; + refType = 2; + }; + F53755A9016C389901DC9062 = { + isa = PBXFileReference; + name = tkMacWinMenu.c; + path = ../generic/tkMacWinMenu.c; + refType = 2; + }; + F53755AA016C389901DC9062 = { + isa = PBXFileReference; + name = tkMain.c; + path = ../generic/tkMain.c; + refType = 2; + }; + F53755AB016C389901DC9062 = { + isa = PBXFileReference; + name = tkMenu.c; + path = ../generic/tkMenu.c; + refType = 2; + }; + F53755AC016C389901DC9062 = { + isa = PBXFileReference; + name = tkMenubutton.c; + path = ../generic/tkMenubutton.c; + refType = 2; + }; + F53755AD016C389901DC9062 = { + isa = PBXFileReference; + name = tkMenuDraw.c; + path = ../generic/tkMenuDraw.c; + refType = 2; + }; + F53755AE016C389901DC9062 = { + isa = PBXFileReference; + name = tkMessage.c; + path = ../generic/tkMessage.c; + refType = 2; + }; + F53755AF016C389901DC9062 = { + isa = PBXFileReference; + name = tkObj.c; + path = ../generic/tkObj.c; + refType = 2; + }; + F53755B0016C389901DC9062 = { + isa = PBXFileReference; + name = tkOldConfig.c; + path = ../generic/tkOldConfig.c; + refType = 2; + }; + F53755B1016C389901DC9062 = { + isa = PBXFileReference; + name = tkOption.c; + path = ../generic/tkOption.c; + refType = 2; + }; + F53755B2016C389901DC9062 = { + isa = PBXFileReference; + name = tkPack.c; + path = ../generic/tkPack.c; + refType = 2; + }; + F53755B3016C389901DC9062 = { + isa = PBXFileReference; + name = tkPlace.c; + path = ../generic/tkPlace.c; + refType = 2; + }; + F53755B4016C389901DC9062 = { + isa = PBXFileReference; + name = tkPointer.c; + path = ../generic/tkPointer.c; + refType = 2; + }; + F53755B5016C389901DC9062 = { + isa = PBXFileReference; + name = tkRectOval.c; + path = ../generic/tkRectOval.c; + refType = 2; + }; + F53755B6016C389901DC9062 = { + isa = PBXFileReference; + name = tkScale.c; + path = ../generic/tkScale.c; + refType = 2; + }; + F53755B7016C389901DC9062 = { + isa = PBXFileReference; + name = tkScrollbar.c; + path = ../generic/tkScrollbar.c; + refType = 2; + }; + F53755B8016C389901DC9062 = { + isa = PBXFileReference; + name = tkSelect.c; + path = ../generic/tkSelect.c; + refType = 2; + }; + F53755B9016C389901DC9062 = { + isa = PBXFileReference; + name = tkStubImg.c; + path = ../generic/tkStubImg.c; + refType = 2; + }; + F53755BA016C389901DC9062 = { + isa = PBXFileReference; + name = tkStubInit.c; + path = ../generic/tkStubInit.c; + refType = 2; + }; + F53755BB016C389901DC9062 = { + isa = PBXFileReference; + name = tkStubLib.c; + path = ../generic/tkStubLib.c; + refType = 2; + }; + F53755BC016C389901DC9062 = { + isa = PBXFileReference; + name = tkTest.c; + path = ../generic/tkTest.c; + refType = 2; + }; + F53755BD016C389901DC9062 = { + isa = PBXFileReference; + name = tkText.c; + path = ../generic/tkText.c; + refType = 2; + }; + F53755BE016C389901DC9062 = { + isa = PBXFileReference; + name = tkTextBTree.c; + path = ../generic/tkTextBTree.c; + refType = 2; + }; + F53755BF016C389901DC9062 = { + isa = PBXFileReference; + name = tkTextDisp.c; + path = ../generic/tkTextDisp.c; + refType = 2; + }; + F53755C0016C389901DC9062 = { + isa = PBXFileReference; + name = tkTextImage.c; + path = ../generic/tkTextImage.c; + refType = 2; + }; + F53755C1016C389901DC9062 = { + isa = PBXFileReference; + name = tkTextIndex.c; + path = ../generic/tkTextIndex.c; + refType = 2; + }; + F53755C2016C389901DC9062 = { + isa = PBXFileReference; + name = tkTextMark.c; + path = ../generic/tkTextMark.c; + refType = 2; + }; + F53755C3016C389901DC9062 = { + isa = PBXFileReference; + name = tkTextTag.c; + path = ../generic/tkTextTag.c; + refType = 2; + }; + F53755C4016C389901DC9062 = { + isa = PBXFileReference; + name = tkTextWind.c; + path = ../generic/tkTextWind.c; + refType = 2; + }; + F53755C5016C389901DC9062 = { + isa = PBXFileReference; + name = tkTrig.c; + path = ../generic/tkTrig.c; + refType = 2; + }; + F53755C6016C389901DC9062 = { + isa = PBXFileReference; + name = tkUtil.c; + path = ../generic/tkUtil.c; + refType = 2; + }; + F53755C7016C389901DC9062 = { + isa = PBXFileReference; + name = tkVisual.c; + path = ../generic/tkVisual.c; + refType = 2; + }; + F53755C8016C389901DC9062 = { + isa = PBXFileReference; + name = tkWindow.c; + path = ../generic/tkWindow.c; + refType = 2; + }; + F53755C9016C389901DC9062 = { + children = ( + F53755CA016C389901DC9062, + F53755CB016C389901DC9062, + ); + isa = PBXGroup; + name = Unix; + refType = 4; + }; + F53755CA016C389901DC9062 = { + isa = PBXFileReference; + name = tkUnix3d.c; + path = ../unix/tkUnix3d.c; + refType = 2; + }; + F53755CB016C389901DC9062 = { + isa = PBXFileReference; + name = tkUnixScale.c; + path = ../unix/tkUnixScale.c; + refType = 2; + }; + F53755CC016C389901DC9062 = { + children = ( + F53755CD016C389901DC9062, + F53755D7016C389901DC9062, + ); + isa = PBXGroup; + name = "X Emulation"; + refType = 4; + }; + F53755CD016C389901DC9062 = { + children = ( + F53755CE016C389901DC9062, + F53755CF016C389901DC9062, + F53755D0016C389901DC9062, + F53755D1016C389901DC9062, + F53755D2016C389901DC9062, + F53755D3016C389901DC9062, + F53755D4016C389901DC9062, + F53755D5016C389901DC9062, + F53755D6016C389901DC9062, + ); + isa = PBXGroup; + name = Headers; + refType = 4; + }; + F53755CE016C389901DC9062 = { + isa = PBXFileReference; + name = xbytes.h; + path = ../xlib/xbytes.h; + refType = 2; + }; + F53755CF016C389901DC9062 = { + isa = PBXFileReference; + name = cursorfont.h; + path = ../xlib/X11/cursorfont.h; + refType = 2; + }; + F53755D0016C389901DC9062 = { + isa = PBXFileReference; + name = keysym.h; + path = ../xlib/X11/keysym.h; + refType = 2; + }; + F53755D1016C389901DC9062 = { + isa = PBXFileReference; + name = keysymdef.h; + path = ../xlib/X11/keysymdef.h; + refType = 2; + }; + F53755D2016C389901DC9062 = { + isa = PBXFileReference; + name = X.h; + path = ../xlib/X11/X.h; + refType = 2; + }; + F53755D3016C389901DC9062 = { + isa = PBXFileReference; + name = Xatom.h; + path = ../xlib/X11/Xatom.h; + refType = 2; + }; + F53755D4016C389901DC9062 = { + isa = PBXFileReference; + name = Xfuncproto.h; + path = ../xlib/X11/Xfuncproto.h; + refType = 2; + }; + F53755D5016C389901DC9062 = { + isa = PBXFileReference; + name = Xlib.h; + path = ../xlib/X11/Xlib.h; + refType = 2; + }; + F53755D6016C389901DC9062 = { + isa = PBXFileReference; + name = Xutil.h; + path = ../xlib/X11/Xutil.h; + refType = 2; + }; + F53755D7016C389901DC9062 = { + children = ( + F53755D8016C389901DC9062, + F53755D9016C389901DC9062, + F53755DA016C389901DC9062, + F53755DB016C389901DC9062, + F53755DC016C389901DC9062, + ); + isa = PBXGroup; + name = Source; + refType = 4; + }; + F53755D8016C389901DC9062 = { + isa = PBXFileReference; + name = xcolors.c; + path = ../xlib/xcolors.c; + refType = 2; + }; + F53755D9016C389901DC9062 = { + isa = PBXFileReference; + name = xdraw.c; + path = ../xlib/xdraw.c; + refType = 2; + }; + F53755DA016C389901DC9062 = { + isa = PBXFileReference; + name = xgc.c; + path = ../xlib/xgc.c; + refType = 2; + }; + F53755DB016C389901DC9062 = { + isa = PBXFileReference; + name = ximage.c; + path = ../xlib/ximage.c; + refType = 2; + }; + F53755DC016C389901DC9062 = { + isa = PBXFileReference; + name = xutil.c; + path = ../xlib/xutil.c; + refType = 2; + }; + F53755DD016C38D201DC9062 = { + children = ( + F53755DE016C38D201DC9062, + F537569F016C4DD401DC9062, + F548F8CF0313CEF0016F146B, + ); + isa = PBXGroup; + name = Products; + refType = 4; + }; + F53755DE016C38D201DC9062 = { + isa = PBXFrameworkReference; + path = Tk.framework; + refType = 3; + }; + F53755DF016C38D201DC9062 = { + buildPhases = ( + F5877FB7031F97ED016F146B, + F53755E0016C38D201DC9062, + F53755E1016C38D301DC9062, + F53755E2016C38D301DC9062, + F53755E3016C38D301DC9062, + F53755E4016C38D301DC9062, + F5B1FC08016FFE3501DC9062, + F51D903F018149BD01DC9062, + F548F8C80313C9E0016F146B, + F52D38C5031F4259016F146B, + F5877FBC031FA968016F146B, + F5C1D51901B88F9A01DC9062, + ); + buildSettings = { + DYLIB_COMPATIBILITY_VERSION = 8.4; + DYLIB_CURRENT_VERSION = 8.4; + FRAMEWORK_SEARCH_PATHS = "\"$(SYMROOT)\""; + FRAMEWORK_VERSION = 8.4; + GLOBAL_CFLAGS = "`source \"${SYMROOT}/Tcl.framework/Resources/tclConfig.sh\"; echo $${}{TCL_EXTRA_CFLAGS} $${}{TCL_DEFS} | sed -e 's|\\\\\\\\\\\\\\\"|\\\"|g' | sed -e 's| -DTCL_WIDE_INT_TYPE=long. long||'` -U_REENTRANT"; + HEADER_SEARCH_PATHS = "../../tcl/generic ../../tcl/unix ../bitmaps ../generic ../xlib"; + INSTALL_PATH = /Library/Frameworks; + LIBRARY_SEARCH_PATHS = ""; + OPTIMIZATION_CFLAGS = "-O0"; + OTHER_CFLAGS = "-DMAC_OSX_TK -DTCL_WIDE_INT_TYPE=\"long long\""; + OTHER_LDFLAGS = "-seg1addr 0xb000000"; + OTHER_LIBTOOL_FLAGS = ""; + OTHER_REZFLAGS = "-i \"../../tcl/generic\" -i \"../generic\""; + PRINCIPAL_CLASS = ""; + PRODUCT_NAME = Tk; + SECTORDER_FLAGS = ""; + TK_MAJOR_VERSION = 8; + TK_MINOR_VERSION = 4; + TK_PATCH_LEVEL = b3; + USE_GCC3_PFE_SUPPORT = NO; + WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas -Wno-unused-variable"; + WRAPPER_EXTENSION = framework; + }; + dependencies = ( + F548F8D20313CF93016F146B, + ); + isa = PBXFrameworkTarget; + name = TkLibrary; + productInstallPath = /Library/Frameworks; + productName = TkLibrary; + productReference = F53755DE016C38D201DC9062; + productSettingsXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> +<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"> +<plist version=\"1.0\"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>Tk</string> + <key>CFBundleGetInfoString</key> + <string>Tk Library 8.4b3 +MacOS X Port by Jim Ingham & Ian Reid +jingham@apple.com +Copyright Apple Computer, Inc 2001</string> + <key>CFBundleIconFile</key> + <string></string> + <key>CFBundleIdentifier</key> + <string>com.tcltk.tklibrary</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>Tk Library 8.4b3</string> + <key>CFBundlePackageType</key> + <string>FMWK</string> + <key>CFBundleShortVersionString</key> + <string>libtk8.4b3</string> + <key>CFBundleSignature</key> + <string>WiSH</string> + <key>CFBundleVersion</key> + <string>8.4b3</string> +</dict> +</plist> +"; + shouldUseHeadermap = 0; + }; + F53755E0016C38D201DC9062 = { + buildActionMask = 2147483647; + files = ( + F53755E5016C390401DC9062, + F53755E6016C390401DC9062, + F53755E7016C390401DC9062, + F53755E8016C390401DC9062, + F53755E9016C390401DC9062, + F53755EA016C390401DC9062, + F53755EB016C390401DC9062, + F53755EC016C390401DC9062, + F53755ED016C390401DC9062, + F53755EE016C390401DC9062, + F53755EF016C390401DC9062, + F53755F0016C390401DC9062, + F53755F1016C390401DC9062, + F53755F2016C390401DC9062, + F53755F3016C390401DC9062, + F53755F4016C390401DC9062, + F53755F5016C390401DC9062, + F53755F6016C390401DC9062, + F53755F7016C390401DC9062, + F53755F8016C390401DC9062, + F53755F9016C390401DC9062, + F53755FA016C390401DC9062, + F53755FB016C390401DC9062, + F53755FC016C397D01DC9062, + F53755FD016C397D01DC9062, + F53755FE016C397D01DC9062, + F53755FF016C397D01DC9062, + F5375600016C397D01DC9062, + F5375601016C397D01DC9062, + F5375602016C397D01DC9062, + F5375603016C397D01DC9062, + F537566E016C3A1F01DC9062, + F537566F016C3A1F01DC9062, + F5375670016C3A1F01DC9062, + F5375671016C3A1F01DC9062, + F5375672016C3A1F01DC9062, + F5375673016C3A1F01DC9062, + F5375674016C3A1F01DC9062, + F5375675016C3A1F01DC9062, + F5375676016C3A1F01DC9062, + F5375693016C3F1001DC9062, + F5375694016C3F1001DC9062, + F5375695016C3F1001DC9062, + F5375696016C3F1001DC9062, + F5375697016C3F1001DC9062, + F5375698016C3F1001DC9062, + F5375699016C3F1001DC9062, + F537569A016C3F1001DC9062, + F537569B016C3F1001DC9062, + F537569C016C3F1001DC9062, + F5BFE59002F8C45B01DC9062, + ); + isa = PBXHeadersBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F53755E1016C38D301DC9062 = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXResourcesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F53755E2016C38D301DC9062 = { + buildActionMask = 2147483647; + files = ( + F5375604016C397D01DC9062, + F5375605016C397D01DC9062, + F5375606016C397D01DC9062, + F5375607016C397D01DC9062, + F5375608016C397D01DC9062, + F5375609016C397D01DC9062, + F537560A016C397D01DC9062, + F537560B016C397D01DC9062, + F537560C016C397D01DC9062, + F537560D016C397D01DC9062, + F537560E016C397D01DC9062, + F537560F016C397D01DC9062, + F5375610016C397D01DC9062, + F5375611016C397D01DC9062, + F5375612016C397D01DC9062, + F5375613016C397D01DC9062, + F5375614016C397D01DC9062, + F5375615016C397D01DC9062, + F5375616016C397D01DC9062, + F5375617016C397D01DC9062, + F5375618016C397D01DC9062, + F5375619016C397D01DC9062, + F537561A016C397D01DC9062, + F537561B016C397D01DC9062, + F537561C016C397D01DC9062, + F537561D016C397D01DC9062, + F537561E016C397D01DC9062, + F537561F016C397D01DC9062, + F5375620016C397D01DC9062, + F5375621016C397D01DC9062, + F5375622016C397D01DC9062, + F5375623016C397D01DC9062, + F5375624016C397D01DC9062, + F5375625016C397D01DC9062, + F5375626016C397D01DC9062, + F5375627016C397D01DC9062, + F5375628016C397D01DC9062, + F5375629016C397D01DC9062, + F537562A016C397D01DC9062, + F537562B016C397D01DC9062, + F537562C016C397D01DC9062, + F537562D016C397D01DC9062, + F537562E016C397D01DC9062, + F537562F016C397D01DC9062, + F5375630016C397D01DC9062, + F5375631016C397D01DC9062, + F5375632016C397D01DC9062, + F5375633016C397D01DC9062, + F5375634016C397D01DC9062, + F5375635016C397D01DC9062, + F5375636016C397D01DC9062, + F5375637016C397D01DC9062, + F5375638016C397D01DC9062, + F5375639016C397D01DC9062, + F537563A016C397D01DC9062, + F537563B016C397D01DC9062, + F537563C016C397D01DC9062, + F537563D016C397D01DC9062, + F537563F016C397D01DC9062, + F5375640016C397D01DC9062, + F5375641016C397D01DC9062, + F5375642016C397D01DC9062, + F5375643016C397D01DC9062, + F5375644016C397D01DC9062, + F5375645016C397D01DC9062, + F5375646016C397D01DC9062, + F5375647016C397D01DC9062, + F5375648016C397D01DC9062, + F5375649016C397D01DC9062, + F537564A016C397D01DC9062, + F537564D016C39A101DC9062, + F537564E016C39A101DC9062, + F537564F016C39A101DC9062, + F5375650016C39A101DC9062, + F5375651016C39A101DC9062, + F5375652016C39A101DC9062, + F5375653016C39A101DC9062, + F5375654016C39A101DC9062, + F5375655016C39A101DC9062, + F5375656016C39A101DC9062, + F5375657016C39A101DC9062, + F5375658016C39A101DC9062, + F5375659016C39A101DC9062, + F537565A016C39A101DC9062, + F537565B016C39A101DC9062, + F537565C016C39A101DC9062, + F537565D016C39A101DC9062, + F537565E016C39A101DC9062, + F537565F016C39A101DC9062, + F5375660016C39A101DC9062, + F5375661016C39A101DC9062, + F5375662016C39A101DC9062, + F5375664016C39A101DC9062, + F5375665016C39A101DC9062, + F5375666016C39A101DC9062, + F5375667016C39A101DC9062, + F5375668016C39A101DC9062, + F537566A016C39A101DC9062, + F537566B016C39A101DC9062, + F537566C016C39F201DC9062, + F537566D016C39F201DC9062, + F5375677016C3A6D01DC9062, + F5375678016C3A6D01DC9062, + F5375679016C3A6D01DC9062, + F537567A016C3A6D01DC9062, + F537567B016C3A6D01DC9062, + F537569E016C49C301DC9062, + F55BC46902B2D38B01DC9062, + F5BFE58D02F8C41501DC9062, + F5BFE58E02F8C41501DC9062, + ); + isa = PBXSourcesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F53755E3016C38D301DC9062 = { + buildActionMask = 2147483647; + files = ( + F51D903E0181474301DC9062, + F537567E016C3ADB01DC9062, + F50D96130196176E01DC9062, + ); + isa = PBXFrameworksBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F53755E4016C38D301DC9062 = { + buildActionMask = 2147483647; + files = ( + F537567F016C3ADB01DC9062, + F5375680016C3ADB01DC9062, + F5375681016C3ADB01DC9062, + F5375682016C3ADB01DC9062, + ); + isa = PBXRezBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F53755E5016C390401DC9062 = { + fileRef = F5375569016C37A601DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53755E6016C390401DC9062 = { + fileRef = F537556A016C37A601DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53755E7016C390401DC9062 = { + fileRef = F537556B016C37A601DC9062; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + Public, + ); + }; + }; + F53755E8016C390401DC9062 = { + fileRef = F537556C016C37A601DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53755E9016C390401DC9062 = { + fileRef = F537556D016C37A601DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53755EA016C390401DC9062 = { + fileRef = F537556E016C37A601DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53755EB016C390401DC9062 = { + fileRef = F537556F016C37A601DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53755EC016C390401DC9062 = { + fileRef = F5375570016C37A601DC9062; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + Public, + ); + }; + }; + F53755ED016C390401DC9062 = { + fileRef = F5375571016C37A601DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53755EE016C390401DC9062 = { + fileRef = F5375572016C37A601DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53755EF016C390401DC9062 = { + fileRef = F5375573016C37A601DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53755F0016C390401DC9062 = { + fileRef = F5375574016C37A601DC9062; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + Private, + ); + }; + }; + F53755F1016C390401DC9062 = { + fileRef = F5375575016C37A601DC9062; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + Private, + ); + }; + }; + F53755F2016C390401DC9062 = { + fileRef = F5375576016C37A601DC9062; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + Private, + ); + }; + }; + F53755F3016C390401DC9062 = { + fileRef = F5375577016C37A601DC9062; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + Private, + ); + }; + }; + F53755F4016C390401DC9062 = { + fileRef = F5375578016C37A601DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53755F5016C390401DC9062 = { + fileRef = F5375579016C37A601DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53755F6016C390401DC9062 = { + fileRef = F537557A016C37A601DC9062; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + Public, + ); + }; + }; + F53755F7016C390401DC9062 = { + fileRef = F537557B016C37A601DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53755F8016C390401DC9062 = { + fileRef = F537557C016C37A601DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53755F9016C390401DC9062 = { + fileRef = F537557D016C37A601DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53755FA016C390401DC9062 = { + fileRef = F537557E016C37A601DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53755FB016C390401DC9062 = { + fileRef = F537557F016C37A601DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53755FC016C397D01DC9062 = { + fileRef = F537553E016C376E01DC9062; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + Public, + ); + }; + }; + F53755FD016C397D01DC9062 = { + fileRef = F537553F016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53755FE016C397D01DC9062 = { + fileRef = F5375540016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53755FF016C397D01DC9062 = { + fileRef = F5375541016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375600016C397D01DC9062 = { + fileRef = F5375542016C376E01DC9062; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + Private, + ); + }; + }; + F5375601016C397D01DC9062 = { + fileRef = F5375543016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375602016C397D01DC9062 = { + fileRef = F5375544016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375603016C397D01DC9062 = { + fileRef = F5375545016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375604016C397D01DC9062 = { + fileRef = F5375580016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375605016C397D01DC9062 = { + fileRef = F5375581016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375606016C397D01DC9062 = { + fileRef = F5375582016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375607016C397D01DC9062 = { + fileRef = F5375583016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375608016C397D01DC9062 = { + fileRef = F5375584016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375609016C397D01DC9062 = { + fileRef = F5375585016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537560A016C397D01DC9062 = { + fileRef = F5375586016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537560B016C397D01DC9062 = { + fileRef = F5375587016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537560C016C397D01DC9062 = { + fileRef = F5375588016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537560D016C397D01DC9062 = { + fileRef = F5375589016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537560E016C397D01DC9062 = { + fileRef = F537558A016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537560F016C397D01DC9062 = { + fileRef = F537558B016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375610016C397D01DC9062 = { + fileRef = F537558C016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375611016C397D01DC9062 = { + fileRef = F537558D016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375612016C397D01DC9062 = { + fileRef = F537558E016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375613016C397D01DC9062 = { + fileRef = F537558F016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375614016C397D01DC9062 = { + fileRef = F5375590016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375615016C397D01DC9062 = { + fileRef = F5375591016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375616016C397D01DC9062 = { + fileRef = F5375592016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375617016C397D01DC9062 = { + fileRef = F5375593016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375618016C397D01DC9062 = { + fileRef = F5375594016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375619016C397D01DC9062 = { + fileRef = F5375595016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537561A016C397D01DC9062 = { + fileRef = F5375596016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537561B016C397D01DC9062 = { + fileRef = F5375597016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537561C016C397D01DC9062 = { + fileRef = F5375598016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537561D016C397D01DC9062 = { + fileRef = F5375599016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537561E016C397D01DC9062 = { + fileRef = F537559A016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537561F016C397D01DC9062 = { + fileRef = F537559B016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375620016C397D01DC9062 = { + fileRef = F537559C016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375621016C397D01DC9062 = { + fileRef = F537559D016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375622016C397D01DC9062 = { + fileRef = F537559E016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375623016C397D01DC9062 = { + fileRef = F537559F016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375624016C397D01DC9062 = { + fileRef = F53755A0016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375625016C397D01DC9062 = { + fileRef = F53755A1016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375626016C397D01DC9062 = { + fileRef = F53755A2016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375627016C397D01DC9062 = { + fileRef = F53755A3016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375628016C397D01DC9062 = { + fileRef = F53755A4016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375629016C397D01DC9062 = { + fileRef = F53755A5016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537562A016C397D01DC9062 = { + fileRef = F53755A6016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537562B016C397D01DC9062 = { + fileRef = F53755A7016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537562C016C397D01DC9062 = { + fileRef = F53755A8016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537562D016C397D01DC9062 = { + fileRef = F53755A9016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537562E016C397D01DC9062 = { + fileRef = F53755AA016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537562F016C397D01DC9062 = { + fileRef = F53755AB016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375630016C397D01DC9062 = { + fileRef = F53755AC016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375631016C397D01DC9062 = { + fileRef = F53755AD016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375632016C397D01DC9062 = { + fileRef = F53755AE016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375633016C397D01DC9062 = { + fileRef = F53755AF016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375634016C397D01DC9062 = { + fileRef = F53755B0016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375635016C397D01DC9062 = { + fileRef = F53755B1016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375636016C397D01DC9062 = { + fileRef = F53755B2016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375637016C397D01DC9062 = { + fileRef = F53755B3016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375638016C397D01DC9062 = { + fileRef = F53755B4016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375639016C397D01DC9062 = { + fileRef = F53755B5016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537563A016C397D01DC9062 = { + fileRef = F53755B6016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537563B016C397D01DC9062 = { + fileRef = F53755B7016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537563C016C397D01DC9062 = { + fileRef = F53755B8016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537563D016C397D01DC9062 = { + fileRef = F53755BA016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537563F016C397D01DC9062 = { + fileRef = F53755BD016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375640016C397D01DC9062 = { + fileRef = F53755BE016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375641016C397D01DC9062 = { + fileRef = F53755BF016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375642016C397D01DC9062 = { + fileRef = F53755C0016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375643016C397D01DC9062 = { + fileRef = F53755C1016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375644016C397D01DC9062 = { + fileRef = F53755C2016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375645016C397D01DC9062 = { + fileRef = F53755C3016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375646016C397D01DC9062 = { + fileRef = F53755C4016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375647016C397D01DC9062 = { + fileRef = F53755C5016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375648016C397D01DC9062 = { + fileRef = F53755C6016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375649016C397D01DC9062 = { + fileRef = F53755C7016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537564A016C397D01DC9062 = { + fileRef = F53755C8016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537564D016C39A101DC9062 = { + fileRef = F5375549016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537564E016C39A101DC9062 = { + fileRef = F537554A016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537564F016C39A101DC9062 = { + fileRef = F537554B016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375650016C39A101DC9062 = { + fileRef = F537554C016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375651016C39A101DC9062 = { + fileRef = F537554D016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375652016C39A101DC9062 = { + fileRef = F537554E016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375653016C39A101DC9062 = { + fileRef = F537554F016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375654016C39A101DC9062 = { + fileRef = F5375550016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375655016C39A101DC9062 = { + fileRef = F5375551016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375656016C39A101DC9062 = { + fileRef = F5375552016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375657016C39A101DC9062 = { + fileRef = F5375553016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375658016C39A101DC9062 = { + fileRef = F5375554016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375659016C39A101DC9062 = { + fileRef = F5375555016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537565A016C39A101DC9062 = { + fileRef = F5375556016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537565B016C39A101DC9062 = { + fileRef = F5375557016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537565C016C39A101DC9062 = { + fileRef = F5375558016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537565D016C39A101DC9062 = { + fileRef = F5375559016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537565E016C39A101DC9062 = { + fileRef = F537555A016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537565F016C39A101DC9062 = { + fileRef = F537555B016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375660016C39A101DC9062 = { + fileRef = F537555C016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375661016C39A101DC9062 = { + fileRef = F537555D016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375662016C39A101DC9062 = { + fileRef = F537555E016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375664016C39A101DC9062 = { + fileRef = F5375560016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375665016C39A101DC9062 = { + fileRef = F5375561016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375666016C39A101DC9062 = { + fileRef = F5375562016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375667016C39A101DC9062 = { + fileRef = F5375564016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375668016C39A101DC9062 = { + fileRef = F5375565016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537566A016C39A101DC9062 = { + fileRef = F5375567016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537566B016C39A101DC9062 = { + fileRef = F5375568016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537566C016C39F201DC9062 = { + fileRef = F53755CA016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537566D016C39F201DC9062 = { + fileRef = F53755CB016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537566E016C3A1F01DC9062 = { + fileRef = F53755CE016C389901DC9062; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + ); + }; + }; + F537566F016C3A1F01DC9062 = { + fileRef = F53755CF016C389901DC9062; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + ); + }; + }; + F5375670016C3A1F01DC9062 = { + fileRef = F53755D0016C389901DC9062; + isa = PBXBuildFile; + settings = { + ATTRIBUTES = ( + ); + }; + }; + F5375671016C3A1F01DC9062 = { + fileRef = F53755D1016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375672016C3A1F01DC9062 = { + fileRef = F53755D2016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375673016C3A1F01DC9062 = { + fileRef = F53755D3016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375674016C3A1F01DC9062 = { + fileRef = F53755D4016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375675016C3A1F01DC9062 = { + fileRef = F53755D5016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375676016C3A1F01DC9062 = { + fileRef = F53755D6016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375677016C3A6D01DC9062 = { + fileRef = F53755D8016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375678016C3A6D01DC9062 = { + fileRef = F53755D9016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375679016C3A6D01DC9062 = { + fileRef = F53755DA016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537567A016C3A6D01DC9062 = { + fileRef = F53755DB016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537567B016C3A6D01DC9062 = { + fileRef = F53755DC016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537567C016C3ADB01DC9062 = { + children = ( + F50D96120196176E01DC9062, + F5875C7B016FEF1D01DC9062, + F537567D016C3ADB01DC9062, + ); + isa = PBXGroup; + name = "External Frameworks"; + refType = 4; + }; + F537567D016C3ADB01DC9062 = { + isa = PBXFrameworkReference; + name = Carbon.framework; + path = /System/Library/Frameworks/Carbon.framework; + refType = 0; + }; + F537567E016C3ADB01DC9062 = { + fileRef = F537567D016C3ADB01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537567F016C3ADB01DC9062 = { + fileRef = F5375533016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375680016C3ADB01DC9062 = { + fileRef = F5375535016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375681016C3ADB01DC9062 = { + fileRef = F5375538016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375682016C3ADB01DC9062 = { + fileRef = F537553A016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375688016C3F1001DC9062 = { + children = ( + F5375689016C3F1001DC9062, + F537568A016C3F1001DC9062, + F537568B016C3F1001DC9062, + F537568C016C3F1001DC9062, + F537568D016C3F1001DC9062, + F537568E016C3F1001DC9062, + F537568F016C3F1001DC9062, + F5375690016C3F1001DC9062, + F5375691016C3F1001DC9062, + F5375692016C3F1001DC9062, + ); + isa = PBXGroup; + name = Bitmaps; + refType = 4; + }; + F5375689016C3F1001DC9062 = { + isa = PBXFileReference; + name = error.bmp; + path = ../bitmaps/error.bmp; + refType = 2; + }; + F537568A016C3F1001DC9062 = { + isa = PBXFileReference; + name = gray12.bmp; + path = ../bitmaps/gray12.bmp; + refType = 2; + }; + F537568B016C3F1001DC9062 = { + isa = PBXFileReference; + name = gray25.bmp; + path = ../bitmaps/gray25.bmp; + refType = 2; + }; + F537568C016C3F1001DC9062 = { + isa = PBXFileReference; + name = gray50.bmp; + path = ../bitmaps/gray50.bmp; + refType = 2; + }; + F537568D016C3F1001DC9062 = { + isa = PBXFileReference; + name = gray75.bmp; + path = ../bitmaps/gray75.bmp; + refType = 2; + }; + F537568E016C3F1001DC9062 = { + isa = PBXFileReference; + name = hourglass.bmp; + path = ../bitmaps/hourglass.bmp; + refType = 2; + }; + F537568F016C3F1001DC9062 = { + isa = PBXFileReference; + name = info.bmp; + path = ../bitmaps/info.bmp; + refType = 2; + }; + F5375690016C3F1001DC9062 = { + isa = PBXFileReference; + name = questhead.bmp; + path = ../bitmaps/questhead.bmp; + refType = 2; + }; + F5375691016C3F1001DC9062 = { + isa = PBXFileReference; + name = question.bmp; + path = ../bitmaps/question.bmp; + refType = 2; + }; + F5375692016C3F1001DC9062 = { + isa = PBXFileReference; + name = warning.bmp; + path = ../bitmaps/warning.bmp; + refType = 2; + }; + F5375693016C3F1001DC9062 = { + fileRef = F5375689016C3F1001DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375694016C3F1001DC9062 = { + fileRef = F537568A016C3F1001DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375695016C3F1001DC9062 = { + fileRef = F537568B016C3F1001DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375696016C3F1001DC9062 = { + fileRef = F537568C016C3F1001DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375697016C3F1001DC9062 = { + fileRef = F537568D016C3F1001DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375698016C3F1001DC9062 = { + fileRef = F537568E016C3F1001DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5375699016C3F1001DC9062 = { + fileRef = F537568F016C3F1001DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537569A016C3F1001DC9062 = { + fileRef = F5375690016C3F1001DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537569B016C3F1001DC9062 = { + fileRef = F5375691016C3F1001DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537569C016C3F1001DC9062 = { + fileRef = F5375692016C3F1001DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537569E016C49C301DC9062 = { + fileRef = F53755BB016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F537569F016C4DD401DC9062 = { + isa = PBXApplicationReference; + path = "Wish Shell.app"; + refType = 3; + }; + F53756A0016C4DD401DC9062 = { + buildPhases = ( + F5877FB8031F982D016F146B, + F53756A1016C4DD401DC9062, + F53756A2016C4DD401DC9062, + F53756A4016C4DD401DC9062, + F53756A6016C4DD401DC9062, + F53756AA016C4DD401DC9062, + F5877FBD031FAC6A016F146B, + ); + buildSettings = { + FRAMEWORK_SEARCH_PATHS = "\"$(SYMROOT)\""; + GLOBAL_CFLAGS = "`source \"${SYMROOT}/Tcl.framework/Resources/tclConfig.sh\"; echo $${}{TCL_EXTRA_CFLAGS} $${}{TCL_DEFS} | sed -e 's|\\\\\\\\\\\\\\\"|\\\"|g' | sed -e 's| -DTCL_WIDE_INT_TYPE=long. long||'` -U_REENTRANT"; + HEADER_SEARCH_PATHS = "../../tcl/generic ../../tcl/unix ../generic ../xlib"; + INSTALL_PATH = /Applications/Utilities; + LIBRARY_SEARCH_PATHS = ""; + OPTIMIZATION_CFLAGS = "-O0"; + OTHER_CFLAGS = "-DMAC_OSX_TK -DTCL_WIDE_INT_TYPE=\"long long\""; + OTHER_LDFLAGS = "-sectcreate __TEXT __info_plist \"$TEMP_DIR/Info.plist\""; + OTHER_REZFLAGS = "-i \"../../tcl/generic\" -i \"../generic\""; + PRODUCT_NAME = "Wish Shell"; + SECTORDER_FLAGS = ""; + USE_GCC3_PFE_SUPPORT = NO; + WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; + WRAPPER_EXTENSION = app; + }; + dependencies = ( + F53756B2016C525F01DC9062, + ); + isa = PBXApplicationTarget; + name = Wish; + productInstallPath = /Applications/Utilities; + productName = "Wish Shell"; + productReference = F537569F016C4DD401DC9062; + productSettingsXML = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> +<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\"> +<plist version=\"1.0\"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleExecutable</key> + <string>Wish Shell</string> + <key>CFBundleGetInfoString</key> + <string>Wish Shell 8.4b3 +MacOS X Port by Jim Ingham & Ian Reid +jingham@apple.com +Copyright Apple Computer, Inc 2002</string> + <key>CFBundleIconFile</key> + <string>Wish.icns</string> + <key>CFBundleIdentifier</key> + <string>com.apple.wish</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>Wish</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleShortVersionString</key> + <string>Wish8.4b3</string> + <key>CFBundleSignature</key> + <string>WiSH</string> + <key>CFBundleVersion</key> + <string>8.4b3</string> +</dict> +</plist> +"; + shouldUseHeadermap = 0; + }; + F53756A1016C4DD401DC9062 = { + buildActionMask = 2147483647; + files = ( + F53756AC016C4E1D01DC9062, + F53756AD016C4E1D01DC9062, + F53756AE016C4E1D01DC9062, + ); + isa = PBXHeadersBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F53756A2016C4DD401DC9062 = { + buildActionMask = 2147483647; + files = ( + F53756A3016C4DD401DC9062, + ); + isa = PBXResourcesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F53756A3016C4DD401DC9062 = { + fileRef = F537553B016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53756A4016C4DD401DC9062 = { + buildActionMask = 2147483647; + files = ( + F53756A5016C4DD401DC9062, + ); + isa = PBXSourcesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F53756A5016C4DD401DC9062 = { + fileRef = F5375548016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53756A6016C4DD401DC9062 = { + buildActionMask = 2147483647; + files = ( + F53756A8016C4DD401DC9062, + F5875C7D016FEF1D01DC9062, + F53756A7016C4DD401DC9062, + F50D96140196176E01DC9062, + F5877FB9031F9F49016F146B, + ); + isa = PBXFrameworksBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F53756A7016C4DD401DC9062 = { + fileRef = F53755DE016C38D201DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53756A8016C4DD401DC9062 = { + fileRef = F537567D016C3ADB01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53756AA016C4DD401DC9062 = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXRezBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F53756AC016C4E1D01DC9062 = { + fileRef = F537556B016C37A601DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53756AD016C4E1D01DC9062 = { + fileRef = F5375570016C37A601DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53756AE016C4E1D01DC9062 = { + fileRef = F537553E016C376E01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F53756B2016C525F01DC9062 = { + isa = PBXTargetDependency; + target = F53755DF016C38D201DC9062; + }; + F548F8C80313C9E0016F146B = { + buildActionMask = 2147483647; + dstPath = "Versions/$(FRAMEWORK_VERSION)"; + dstSubfolderSpec = 1; + files = ( + F5877FBA031F9F4B016F146B, + ); + isa = PBXCopyFilesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F548F8CA0313CEF0016F146B = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXHeadersBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F548F8CB0313CEF0016F146B = { + buildActionMask = 2147483647; + files = ( + F548F8D10313CF14016F146B, + F548F8D00313CF11016F146B, + ); + isa = PBXSourcesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F548F8CC0313CEF0016F146B = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXFrameworksBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F548F8CD0313CEF0016F146B = { + buildActionMask = 2147483647; + files = ( + ); + isa = PBXRezBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F548F8CE0313CEF0016F146B = { + buildPhases = ( + F548F8CA0313CEF0016F146B, + F548F8CB0313CEF0016F146B, + F548F8CC0313CEF0016F146B, + F548F8CD0313CEF0016F146B, + ); + buildSettings = { + GLOBAL_CFLAGS = "`source \"${SYMROOT}/Tcl.framework/Resources/tclConfig.sh\"; echo $${}{TCL_EXTRA_CFLAGS} $${}{TCL_DEFS} | sed -e 's|\\\\\\\\\\\\\\\"|\\\"|g' | sed -e 's| -DTCL_WIDE_INT_TYPE=long. long||'` -U_REENTRANT"; + HEADER_SEARCH_PATHS = "../../tcl/generic ../../tcl/unix ../generic ../xlib"; + LIBRARY_STYLE = STATIC; + OPTIMIZATION_CFLAGS = "-O0"; + OTHER_CFLAGS = "-DMAC_OSX_TK -DTCL_WIDE_INT_TYPE=\"long long\""; + OTHER_LDFLAGS = ""; + OTHER_LIBTOOL_FLAGS = ""; + PRODUCT_NAME = libtkstub8.4.a; + REZ_EXECUTABLE = YES; + SECTORDER_FLAGS = ""; + WARNING_CFLAGS = "-Wmost -Wno-four-char-constants -Wno-unknown-pragmas"; + }; + dependencies = ( + ); + isa = PBXLibraryTarget; + name = TkStubLibrary; + productInstallPath = /usr/local/lib; + productName = TkStub; + productReference = F548F8CF0313CEF0016F146B; + shouldUseHeadermap = 0; + }; + F548F8CF0313CEF0016F146B = { + isa = PBXLibraryReference; + path = libtkstub8.4.a; + refType = 3; + }; + F548F8D00313CF11016F146B = { + fileRef = F53755B9016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F548F8D10313CF14016F146B = { + fileRef = F53755BB016C389901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F548F8D20313CF93016F146B = { + isa = PBXTargetDependency; + target = F548F8CE0313CEF0016F146B; + }; + F55BC46802B2D38B01DC9062 = { + isa = PBXFileReference; + name = tkPanedWindow.c; + path = ../generic/tkPanedWindow.c; + refType = 2; + }; + F55BC46902B2D38B01DC9062 = { + fileRef = F55BC46802B2D38B01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F55BC46A02B2D3F301DC9062 = { + isa = PBXFileReference; + name = panedwindow.tcl; + path = ../library/panedwindow.tcl; + refType = 2; + }; + F55BC46B02B2D3F301DC9062 = { + fileRef = F55BC46A02B2D3F301DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5875C7B016FEF1D01DC9062 = { + isa = PBXFrameworkReference; + path = Tcl.framework; + refType = 3; + }; + F5875C7D016FEF1D01DC9062 = { + fileRef = F5875C7B016FEF1D01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5877FB7031F97ED016F146B = { + buildActionMask = 8; + files = ( + ); + generatedFileNames = ( + ); + isa = PBXShellScriptBuildPhase; + neededFileNames = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "# ensure we can overwrite a previous install\nif [ -d \"${INSTALL_ROOT}${INSTALL_PATH}/${PRODUCT_NAME}.${WRAPPER_EXTENSION}\" ]; then\n chmod -RH u+w \"${INSTALL_ROOT}${INSTALL_PATH}/${PRODUCT_NAME}.${WRAPPER_EXTENSION}\"\nfi"; + }; + F5877FB8031F982D016F146B = { + buildActionMask = 8; + files = ( + ); + generatedFileNames = ( + ); + isa = PBXShellScriptBuildPhase; + neededFileNames = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "# ensure we can overwrite a previous install\nif [ -d \"${INSTALL_ROOT}${INSTALL_PATH}/${PRODUCT_NAME}.${WRAPPER_EXTENSION}\" ]; then\n chmod -RH u+w \"${INSTALL_ROOT}${INSTALL_PATH}/${PRODUCT_NAME}.${WRAPPER_EXTENSION}\"\nfi"; + }; + F5877FB9031F9F49016F146B = { + fileRef = F548F8CF0313CEF0016F146B; + isa = PBXBuildFile; + settings = { + }; + }; + F5877FBA031F9F4B016F146B = { + fileRef = F548F8CF0313CEF0016F146B; + isa = PBXBuildFile; + settings = { + }; + }; + F5877FBC031FA968016F146B = { + buildActionMask = 8; + files = ( + ); + generatedFileNames = ( + ); + isa = PBXShellScriptBuildPhase; + neededFileNames = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "# redo prebinding\nif [ ! -d \"${INSTALL_ROOT}/usr/lib\" ]; then ln -fs /usr/lib \"${INSTALL_ROOT}/usr/\"; RM_USRLIB=1; fi\nif [ ! -d \"${INSTALL_ROOT}/System\" ]; then ln -fs /System \"${INSTALL_ROOT}/\"; RM_SYSTEM=1; fi\nredo_prebinding -r \"${INSTALL_ROOT}\" \"${INSTALL_ROOT}${INSTALL_PATH}/${PRODUCT_NAME}.${WRAPPER_EXTENSION}/Versions/${FRAMEWORK_VERSION}/${PRODUCT_NAME}\"\nif [ -n \"${RM_USRLIB:-}\" ]; then rm -f \"${INSTALL_ROOT}/usr/lib\"; fi\nif [ -n \"${RM_SYSTEM:-}\" ]; then rm -f ${INSTALL_ROOT}/System; fi"; + }; + F5877FBD031FAC6A016F146B = { + buildActionMask = 8; + files = ( + ); + generatedFileNames = ( + ); + isa = PBXShellScriptBuildPhase; + neededFileNames = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "# redo prebinding\nif [ ! -d \"${INSTALL_ROOT}/usr/lib\" ]; then ln -fs /usr/lib \"${INSTALL_ROOT}/usr/\"; RM_USRLIB=1; fi\nif [ ! -d \"${INSTALL_ROOT}/System\" ]; then ln -fs /System \"${INSTALL_ROOT}/\"; RM_SYSTEM=1; fi\nredo_prebinding -r \"${INSTALL_ROOT}\" \"${INSTALL_ROOT}${INSTALL_PATH}/${PRODUCT_NAME}.${WRAPPER_EXTENSION}/Contents/MacOS/${PRODUCT_NAME}\"\nif [ -n \"${RM_USRLIB:-}\" ]; then rm -f \"${INSTALL_ROOT}/usr/lib\"; fi\nif [ -n \"${RM_SYSTEM:-}\" ]; then rm -f ${INSTALL_ROOT}/System; fi"; + }; + F5B1FC08016FFE3501DC9062 = { + buildActionMask = 2147483647; + dstPath = "Versions/$(FRAMEWORK_VERSION)/Resources/Scripts"; + dstSubfolderSpec = 1; + files = ( + F5B1FC09016FFE3501DC9062, + F5B1FC0A016FFE3501DC9062, + F5B1FC0B016FFE3501DC9062, + F5B1FC0C016FFE3501DC9062, + F5B1FC0D016FFE3501DC9062, + F5B1FC0E016FFE3501DC9062, + F5B1FC0F016FFE3501DC9062, + F5B1FC10016FFE3501DC9062, + F5B1FC11016FFE3501DC9062, + F5B1FC12016FFE3501DC9062, + F5B1FC13016FFE3501DC9062, + F5B1FC14016FFE3501DC9062, + F5B1FC15016FFE3501DC9062, + F5B1FC16016FFE3501DC9062, + F5B1FC17016FFE3501DC9062, + F5B1FC18016FFE3501DC9062, + F5B1FC19016FFE3501DC9062, + F5B1FC1A016FFE3501DC9062, + F55BC46B02B2D3F301DC9062, + F5B1FC1B016FFE3501DC9062, + F5B1FC1C016FFE3501DC9062, + F5B1FC1D016FFE3501DC9062, + F5B1FC1E016FFE3501DC9062, + F5B1FC1F016FFE3501DC9062, + F5B1FC20016FFE3501DC9062, + F5B1FC21016FFE3501DC9062, + F5B1FC22016FFE3501DC9062, + F5B1FC23016FFE3501DC9062, + F5B1FC24016FFE3501DC9062, + F5B1FC25016FFE3501DC9062, + F5B1FC26016FFE3501DC9062, + ); + isa = PBXCopyFilesBuildPhase; + runOnlyForDeploymentPostprocessing = 0; + }; + F5B1FC09016FFE3501DC9062 = { + fileRef = F5DF0928016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC0A016FFE3501DC9062 = { + fileRef = F5DF0929016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC0B016FFE3501DC9062 = { + fileRef = F5DF092A016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC0C016FFE3501DC9062 = { + fileRef = F5DF092B016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC0D016FFE3501DC9062 = { + fileRef = F5DF092C016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC0E016FFE3501DC9062 = { + fileRef = F5DF092D016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC0F016FFE3501DC9062 = { + fileRef = F5DF092E016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC10016FFE3501DC9062 = { + fileRef = F5DF092F016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC11016FFE3501DC9062 = { + fileRef = F5DF0930016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC12016FFE3501DC9062 = { + fileRef = F5DF0931016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC13016FFE3501DC9062 = { + fileRef = F5DF0932016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC14016FFE3501DC9062 = { + fileRef = F5DF0933016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC15016FFE3501DC9062 = { + fileRef = F5DF0934016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC16016FFE3501DC9062 = { + fileRef = F5DF0935016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC17016FFE3501DC9062 = { + fileRef = F5DF0936016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC18016FFE3501DC9062 = { + fileRef = F5DF0937016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC19016FFE3501DC9062 = { + fileRef = F5DF0938016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC1A016FFE3501DC9062 = { + fileRef = F5DF0939016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC1B016FFE3501DC9062 = { + fileRef = F5DF093A016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC1C016FFE3501DC9062 = { + fileRef = F5DF093B016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC1D016FFE3501DC9062 = { + fileRef = F5DF093C016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC1E016FFE3501DC9062 = { + fileRef = F5DF093D016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC1F016FFE3501DC9062 = { + fileRef = F5DF093E016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC20016FFE3501DC9062 = { + fileRef = F5DF093F016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC21016FFE3501DC9062 = { + fileRef = F5DF0940016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC22016FFE3501DC9062 = { + fileRef = F5DF0941016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC23016FFE3501DC9062 = { + fileRef = F5DF0942016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC24016FFE3501DC9062 = { + fileRef = F5DF0943016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC25016FFE3501DC9062 = { + fileRef = F5DF0944016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5B1FC26016FFE3501DC9062 = { + fileRef = F5DF0945016CD3F901DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5BFE58B02F8C41501DC9062 = { + isa = PBXFileReference; + name = tkStyle.c; + path = ../generic/tkStyle.c; + refType = 2; + }; + F5BFE58C02F8C41501DC9062 = { + isa = PBXFileReference; + name = tkUndo.c; + path = ../generic/tkUndo.c; + refType = 2; + }; + F5BFE58D02F8C41501DC9062 = { + fileRef = F5BFE58B02F8C41501DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5BFE58E02F8C41501DC9062 = { + fileRef = F5BFE58C02F8C41501DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5BFE58F02F8C45B01DC9062 = { + isa = PBXFileReference; + name = tkUndo.h; + path = ../generic/tkUndo.h; + refType = 2; + }; + F5BFE59002F8C45B01DC9062 = { + fileRef = F5BFE58F02F8C45B01DC9062; + isa = PBXBuildFile; + settings = { + }; + }; + F5C1D51901B88F9A01DC9062 = { + buildActionMask = 8; + files = ( + ); + generatedFileNames = ( + ); + isa = PBXShellScriptBuildPhase; + neededFileNames = ( + ); + runOnlyForDeploymentPostprocessing = 1; + shellPath = /bin/sh; + shellScript = "#source buildConfig"; + }; + F5C88659017D625C01DC9062 = { + children = ( + F5C8865A017D625C01DC9062, + F5C8865B017D625C01DC9062, + ); + isa = PBXGroup; + name = "Header Tools"; + refType = 4; + }; + F5C8865A017D625C01DC9062 = { + isa = PBXFileReference; + name = tk.decls; + path = ../generic/tk.decls; + refType = 2; + }; + F5C8865B017D625C01DC9062 = { + isa = PBXFileReference; + name = tkInt.decls; + path = ../generic/tkInt.decls; + refType = 2; + }; + F5DF07A7016CD03801DC9062 = { + children = ( + F5DF0928016CD3F901DC9062, + F5DF0929016CD3F901DC9062, + F5DF092A016CD3F901DC9062, + F5DF092B016CD3F901DC9062, + F5DF092C016CD3F901DC9062, + F5DF092D016CD3F901DC9062, + F5DF092E016CD3F901DC9062, + F5DF092F016CD3F901DC9062, + F5DF0930016CD3F901DC9062, + F5DF0931016CD3F901DC9062, + F5DF0932016CD3F901DC9062, + F5DF0933016CD3F901DC9062, + F5DF0934016CD3F901DC9062, + F5DF0935016CD3F901DC9062, + F5DF0936016CD3F901DC9062, + F5DF0937016CD3F901DC9062, + F5DF0938016CD3F901DC9062, + F5DF0939016CD3F901DC9062, + F55BC46A02B2D3F301DC9062, + F5DF093A016CD3F901DC9062, + F5DF093B016CD3F901DC9062, + F5DF093C016CD3F901DC9062, + F5DF093D016CD3F901DC9062, + F5DF093E016CD3F901DC9062, + F5DF093F016CD3F901DC9062, + F5DF0940016CD3F901DC9062, + F5DF0941016CD3F901DC9062, + F5DF0942016CD3F901DC9062, + F5DF0943016CD3F901DC9062, + F5DF0944016CD3F901DC9062, + F5DF0945016CD3F901DC9062, + ); + isa = PBXGroup; + name = Scripts; + refType = 4; + }; + F5DF0928016CD3F901DC9062 = { + isa = PBXFileReference; + name = bgerror.tcl; + path = ../library/bgerror.tcl; + refType = 2; + }; + F5DF0929016CD3F901DC9062 = { + isa = PBXFileReference; + name = button.tcl; + path = ../library/button.tcl; + refType = 2; + }; + F5DF092A016CD3F901DC9062 = { + isa = PBXFileReference; + name = choosedir.tcl; + path = ../library/choosedir.tcl; + refType = 2; + }; + F5DF092B016CD3F901DC9062 = { + isa = PBXFileReference; + name = clrpick.tcl; + path = ../library/clrpick.tcl; + refType = 2; + }; + F5DF092C016CD3F901DC9062 = { + isa = PBXFileReference; + name = comdlg.tcl; + path = ../library/comdlg.tcl; + refType = 2; + }; + F5DF092D016CD3F901DC9062 = { + isa = PBXFileReference; + name = console.tcl; + path = ../library/console.tcl; + refType = 2; + }; + F5DF092E016CD3F901DC9062 = { + includeInIndex = 0; + isa = PBXFolderReference; + name = demos; + path = ../library/demos; + refType = 2; + }; + F5DF092F016CD3F901DC9062 = { + isa = PBXFileReference; + name = dialog.tcl; + path = ../library/dialog.tcl; + refType = 2; + }; + F5DF0930016CD3F901DC9062 = { + isa = PBXFileReference; + name = entry.tcl; + path = ../library/entry.tcl; + refType = 2; + }; + F5DF0931016CD3F901DC9062 = { + isa = PBXFileReference; + name = focus.tcl; + path = ../library/focus.tcl; + refType = 2; + }; + F5DF0932016CD3F901DC9062 = { + includeInIndex = 0; + isa = PBXFolderReference; + name = images; + path = ../library/images; + refType = 2; + }; + F5DF0933016CD3F901DC9062 = { + isa = PBXFileReference; + name = listbox.tcl; + path = ../library/listbox.tcl; + refType = 2; + }; + F5DF0934016CD3F901DC9062 = { + isa = PBXFileReference; + name = menu.tcl; + path = ../library/menu.tcl; + refType = 2; + }; + F5DF0935016CD3F901DC9062 = { + isa = PBXFileReference; + name = msgbox.tcl; + path = ../library/msgbox.tcl; + refType = 2; + }; + F5DF0936016CD3F901DC9062 = { + includeInIndex = 0; + isa = PBXFolderReference; + name = msgs; + path = ../library/msgs; + refType = 2; + }; + F5DF0937016CD3F901DC9062 = { + isa = PBXFileReference; + name = obsolete.tcl; + path = ../library/obsolete.tcl; + refType = 2; + }; + F5DF0938016CD3F901DC9062 = { + isa = PBXFileReference; + name = optMenu.tcl; + path = ../library/optMenu.tcl; + refType = 2; + }; + F5DF0939016CD3F901DC9062 = { + isa = PBXFileReference; + name = palette.tcl; + path = ../library/palette.tcl; + refType = 2; + }; + F5DF093A016CD3F901DC9062 = { + isa = PBXFileReference; + name = prolog.ps; + path = ../library/prolog.ps; + refType = 2; + }; + F5DF093B016CD3F901DC9062 = { + isa = PBXFileReference; + name = safetk.tcl; + path = ../library/safetk.tcl; + refType = 2; + }; + F5DF093C016CD3F901DC9062 = { + isa = PBXFileReference; + name = scale.tcl; + path = ../library/scale.tcl; + refType = 2; + }; + F5DF093D016CD3F901DC9062 = { + isa = PBXFileReference; + name = scrlbar.tcl; + path = ../library/scrlbar.tcl; + refType = 2; + }; + F5DF093E016CD3F901DC9062 = { + isa = PBXFileReference; + name = spinbox.tcl; + path = ../library/spinbox.tcl; + refType = 2; + }; + F5DF093F016CD3F901DC9062 = { + isa = PBXFileReference; + name = tclIndex; + path = ../library/tclIndex; + refType = 2; + }; + F5DF0940016CD3F901DC9062 = { + isa = PBXFileReference; + name = tearoff.tcl; + path = ../library/tearoff.tcl; + refType = 2; + }; + F5DF0941016CD3F901DC9062 = { + isa = PBXFileReference; + name = text.tcl; + path = ../library/text.tcl; + refType = 2; + }; + F5DF0942016CD3F901DC9062 = { + isa = PBXFileReference; + name = tk.tcl; + path = ../library/tk.tcl; + refType = 2; + }; + F5DF0943016CD3F901DC9062 = { + isa = PBXFileReference; + name = tkfbox.tcl; + path = ../library/tkfbox.tcl; + refType = 2; + }; + F5DF0944016CD3F901DC9062 = { + isa = PBXFileReference; + name = unsupported.tcl; + path = ../library/unsupported.tcl; + refType = 2; + }; + F5DF0945016CD3F901DC9062 = { + isa = PBXFileReference; + name = xmfbox.tcl; + path = ../library/xmfbox.tcl; + refType = 2; + }; + }; + rootObject = F537552A016C352C01DC9062; +} diff --git a/macosx/tclets.r b/macosx/tclets.r new file mode 100644 index 0000000..ce68db4 --- /dev/null +++ b/macosx/tclets.r @@ -0,0 +1,172 @@ +/* + * tclets.r -- + * + */ + +/* + * New style DLOG templates have an extra field for the positioning + * options for the Dialog Box. We will not use this, for now, so we + * turn it off here. + */ + +#define DLOG_RezTemplateVersion 0 + +#include <Types.r> +#include <SysTypes.r> +#include <AEUserTermTypes.r> + +/* + * We now load the Tclets code into the resource fork + */ + +#define TK_LIBRARY_RESOURCES 3000 + +read 'TEXT' (TK_LIBRARY_RESOURCES+114, "tclshrc", purgeable) + "::mac:tclets.tcl"; + +data 'icns' (-16455) { + $"6963 6E73 0000 08F8 6963 7323 0000 0048" /* icns...øics#...H */ + $"0100 02EE 05CE 09EE 13DE 23FF 47CE 86C6" /* ...î.ÎÆî.Þ#ÿG렮 */ + $"4681 22C2 12C4 0888 0410 0220 0140 0080" /* F"Â.Ä.ˆ... .@.€ */ + $"0100 03EE 07CE 0FEE 1FFE 3FFF 7FFE FFFE" /* ...î.Î.î.þ?ÿ.þÿþ */ + $"7FFF 3FFE 1FFC 0FF8 07F0 03E0 01C0 0080" /* .ÿ?þ.ü.ø.ð.à.À.€ */ + $"6963 7334 0000 0088 0000 000F 0000 0000" /* ics4...ˆ........ */ + $"0000 00FC F6D0 FFF0 0000 0FC5 DD00 F6F0" /* ...üöÐÿð...ÅÝ.öð */ + $"0000 FCCD 66F0 F6F0 000F CC6E 66CE F6F0" /* ..üÍfðöð..ÌnfÎöð */ + $"00FC CC6E 67EF F6FF 0FCC CD66 66CC F6F0" /* .üÌngïöÿ.ÌÍffÌöð */ + $"FCCC CDDC 66CC CFA0 0FCC CD6C EDCC CC0F" /* üÌÍÜfÌÏ .ÌÍlíÌÌ. */ + $"00FC CC6C E6CC CCF0 000F CC6C 66CC CF00" /* .üÌlæÌÌð..ÌlfÌÏ. */ + $"0000 FCCC 6CCC F000 0000 0FCC DCCF 0000" /* ..üÌlÌð....ÌÜÏ.. */ + $"0000 00FD DCF0 0000 0000 000F CF00 0000" /* ...ýÜð......Ï... */ + $"0000 0000 F000 0000 6963 7338 0000 0108" /* ....ð...ics8.... */ + $"0000 0000 0000 00FF 0000 0000 0000 0000" /* .......ÿ........ */ + $"0000 0000 0000 FF2B FFEC 7F00 FFFF FF00" /* ......ÿ+ÿì..ÿÿÿ. */ + $"0000 0000 00FF 2BB0 7F7F 0000 FFEC FF00" /* .....ÿ+°....ÿìÿ. */ + $"0000 0000 FF2B 2B7F ECEC FF00 FFEC FF00" /* ....ÿ++.ììÿ.ÿìÿ. */ + $"0000 00FF 2B2B ECFC ECEC 2BFB FFEC FF00" /* ...ÿ++ìüìì+ûÿìÿ. */ + $"0000 FF2B 2B2B ECFC ECC0 FBFF FFEC FFFF" /* ..ÿ+++ìüìÀûÿÿìÿÿ */ + $"00FF 2B2B 2B7F ECEC ECEC 2B2B FFEC FF00" /* .ÿ+++.ìììì++ÿìÿ. */ + $"FF2B 2B2B 2B7F 7FF6 ECEC 2B2B 2BFF FD00" /* ÿ++++..öìì+++ÿý. */ + $"00FF 2B2B 2B7F ECF6 FCF9 2B2B 2B2B 00FF" /* .ÿ+++.ìöüù++++.ÿ */ + $"0000 FF2B 2B2B ECF6 FCEC 2B2B 2B2B FF00" /* ..ÿ+++ìöüì++++ÿ. */ + $"0000 00FF 2B2B ECF6 ECEC 2B2B 2BFF 0000" /* ...ÿ++ìöìì+++ÿ.. */ + $"0000 0000 FF2B 2BF6 EC2B 2B2B FF00 0000" /* ....ÿ++öì+++ÿ... */ + $"0000 0000 00FF 2BF6 F92B 2BFF 0000 0000" /* .....ÿ+öù++ÿ.... */ + $"0000 0000 0000 FFF9 F92B FF00 0000 0000" /* ......ÿùù+ÿ..... */ + $"0000 0000 0000 00FF 2BFF 0000 0000 0000" /* .......ÿ+ÿ...... */ + $"0000 0000 0000 0000 FF00 0000 0000 0000" /* ........ÿ....... */ + $"4943 4E23 0000 0108 0001 0000 0002 8000" /* ICN#..........€. */ + $"0004 78F8 0008 70F8 0010 F0F8 0021 E8F8" /* ..xø..pø..ðø.!èø */ + $"0043 C4F8 0081 FAF8 0107 F1F8 0207 F0F8" /* .CÄø.úø..ñø..ðø */ + $"0407 F7FF 0807 E3FE 1007 E1FC 200E E0F8" /* ..÷ÿ..ãþ..áü .àø */ + $"4002 E074 800E E022 400E E001 200E C002" /* @.àt€.à"@.à. .À. */ + $"1006 E004 0806 C008 0406 E010 0202 C020" /* ..à...À...à...À */ + $"0102 C040 0080 8080 0040 0100 0020 0200" /* ..À@.€€€.@... .. */ + $"0010 0400 0008 0800 0004 1000 0002 2000" /* .............. . */ + $"0001 4000 0000 8000 0001 0000 0003 8000" /* ..@...€.......€. */ + $"0007 F8F8 000F F0F8 001F F0F8 003F F8F8" /* ..øø..ðø..ðø.?øø */ + $"007F FCF8 00FF FEF8 01FF FFF8 03FF FFF8" /* ..üø.ÿþø.ÿÿø.ÿÿø */ + $"07FF FFFF 0FFF FFFE 1FFF FFFC 3FFF FFF8" /* .ÿÿÿ.ÿÿþ.ÿÿü?ÿÿø */ + $"7FFF FFFC FFFF FFFE 7FFF FFFF 3FFF FFFE" /* .ÿÿüÿÿÿþ.ÿÿÿ?ÿÿþ */ + $"1FFF FFFC 0FFF FFF8 07FF FFF0 03FF FFE0" /* .ÿÿü.ÿÿø.ÿÿð.ÿÿà */ + $"01FF FFC0 00FF FF80 007F FF00 003F FE00" /* .ÿÿÀ.ÿÿ€..ÿ..?þ. */ + $"001F FC00 000F F800 0007 F000 0003 E000" /* ..ü...ø...ð...à. */ + $"0001 C000 0000 8000 6963 6C34 0000 0208" /* ..À...€.icl4.... */ + $"0000 0000 0000 000F 0000 0000 0000 0000" /* ................ */ + $"0000 0000 0000 00FC F000 0000 0000 0000" /* .......üð....... */ + $"0000 0000 0000 0FCC CFD6 D000 FFFF F000" /* .......ÌÏÖÐ.ÿÿð. */ + $"0000 0000 0000 FCCC C556 0000 F767 F000" /* ......üÌÅV..÷gð. */ + $"0000 0000 000F CCCC 566F 0000 F676 F000" /* ......ÌÌVo..övð. */ + $"0000 0000 00FC CCC5 6F5C F000 F767 F000" /* .....üÌÅo\ð.÷gð. */ + $"0000 0000 0FCC CC66 66CC 0F00 F676 F000" /* .....ÌÌffÌ..övð. */ + $"0000 0000 FCCC CCD5 5666 FCF0 F767 F000" /* ....üÌÌÕVfüð÷gð. */ + $"0000 000F CCCC C656 5667 CCCF F676 F000" /* ....ÌÌÆVVgÌÏövð. */ + $"0000 00FC CCCC C6E5 5566 CCCC F767 F000" /* ...üÌÌÆåUfÌÌ÷gð. */ + $"0000 0FCC CCCC C656 5657 CFFF F676 FFFF" /* ...ÌÌÌÆVVWÏÿövÿÿ */ + $"0000 FCCC CCCC C6E5 565C CCF7 6767 67F0" /* ..üÌÌÌÆåV\Ì÷gggð */ + $"000F CCCC CCCC C655 565C CCCF 7676 7F00" /* ..ÌÌÌÌÆUV\ÌÏvv.. */ + $"00FC CCCC CCCC 7660 556C CCCC F767 F000" /* .üÌÌÌÌv`UlÌÌ÷gð. */ + $"0FCC CCCC CCCC CD5D 567C CCCC CF7F CF00" /* .ÌÌÌÌÌÍ]V|ÌÌÏ.Ï. */ + $"FCCC CCCC CCCC 6660 556C CCCC CCFC CCF0" /* üÌÌÌÌÌf`UlÌÌÌüÌð */ + $"0FCC CCCC CCCC 665C 565C CCCC CCCC CCCF" /* .ÌÌÌÌÌf\V\ÌÌÌÌÌÏ */ + $"00FC CCCC CCCC 6660 E6DC CCCC CCCC CCF0" /* .üÌÌÌÌf`æÜÌÌÌÌÌð */ + $"000F CCCC CCCC C650 656C CCCC CCCC CF00" /* ..ÌÌÌÌÆPelÌÌÌÌÏ. */ + $"0000 FCCC CCCC C6EC 5ECC CCCC CCCC F000" /* ..üÌÌÌÆì^ÌÌÌÌÌð. */ + $"0000 0FCC CCCC C650 566C CCCC CCCF 0000" /* ...ÌÌÌÆPVlÌÌÌÏ.. */ + $"0000 00FC CCCC CC50 D5CC CCCC CCF0 0000" /* ...üÌÌÌPÕÌÌÌÌð.. */ + $"0000 000F CCCC CC50 56CC CCCC CF00 0000" /* ....ÌÌÌPVÌÌÌÏ... */ + $"0000 0000 FCCC CCD0 5CCC CCCC F000 0000" /* ....üÌÌÐ\ÌÌÌð... */ + $"0000 0000 0FCC CCD0 DCCC CCCF 0000 0000" /* .....ÌÌÐÜÌÌÏ.... */ + $"0000 0000 00FC CCD0 DCCC CCF0 0000 0000" /* .....üÌÐÜÌÌð.... */ + $"0000 0000 000F CCD0 DCCC CF00 0000 0000" /* ......ÌÐÜÌÏ..... */ + $"0000 0000 0000 FCC0 CCCC F000 0000 0000" /* ......üÀÌÌð..... */ + $"0000 0000 0000 0FCD CCCF 0000 0000 0000" /* .......ÍÌÏ...... */ + $"0000 0000 0000 00FC CCF0 0000 0000 0000" /* .......üÌð...... */ + $"0000 0000 0000 000F CF00 0000 0000 0000" /* ........Ï....... */ + $"0000 0000 0000 0000 F000 0000 0000 0000" /* ........ð....... */ + $"6963 6C38 0000 0408 0000 0000 0000 0000" /* icl8............ */ + $"0000 0000 0000 00FF 0000 0000 0000 0000" /* .......ÿ........ */ + $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ + $"0000 0000 0000 FF2B FF00 0000 0000 0000" /* ......ÿ+ÿ....... */ + $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ + $"0000 0000 00FF 2B2B 2BFF 7FEC 7F00 0000" /* .....ÿ+++ÿ.ì.... */ + $"FFFF FFFF FF00 0000 0000 0000 0000 0000" /* ÿÿÿÿÿ........... */ + $"0000 0000 FF2B 2B2B 2BB0 B0EC 0000 0000" /* ....ÿ++++°°ì.... */ + $"FFC0 ECC0 FF00 0000 0000 0000 0000 0000" /* ÿÀìÀÿ........... */ + $"0000 00FF 2B2B 2B2B B0EC ECFF 0000 0000" /* ...ÿ++++°ììÿ.... */ + $"FFEC C0EC FF00 0000 0000 0000 0000 0000" /* ÿìÀìÿ........... */ + $"0000 FF2B 2B2B 2BB0 ECFF B02B FF00 0000" /* ..ÿ++++°ìÿ°+ÿ... */ + $"FFC0 ECC0 FF00 0000 0000 0000 0000 0000" /* ÿÀìÀÿ........... */ + $"00FF 2B2B 2B2B ECEC ECEC 2B2B 00FF 0000" /* .ÿ++++ìììì++.ÿ.. */ + $"FFEC C0EC FF00 0000 0000 0000 0000 0000" /* ÿìÀìÿ........... */ + $"FF2B 2B2B 2B2B F9B0 B0EC ECEC FF2B FF00" /* ÿ+++++ù°°ìììÿ+ÿ. */ + $"FFC0 ECC0 FF00 0000 0000 0000 0000 00FF" /* ÿÀìÀÿ..........ÿ */ + $"2B2B 2B2B 2BEC B0EC B0EC ECC0 2B2B 2BFF" /* +++++ì°ì°ììÀ+++ÿ */ + $"FFEC C0EC FF00 0000 0000 0000 0000 FF2B" /* ÿìÀìÿ.........ÿ+ */ + $"2B2B 2B2B 2BEC FCB0 B0B0 ECEC 2B2B 2B2B" /* +++++ìü°°°ìì++++ */ + $"FFC0 ECC0 FF00 0000 0000 0000 00FF 2B2B" /* ÿÀìÀÿ........ÿ++ */ + $"2B2B 2B2B 2BEC B0EC B0EC B0C0 2BFF FFFF" /* +++++ì°ì°ì°À+ÿÿÿ */ + $"FFEC C0EC FFFF FFFF 0000 0000 FF2B 2B2B" /* ÿìÀìÿÿÿÿ....ÿ+++ */ + $"2B2B 2B2B 2BEC FCB0 B0EC B02B 2B2B FFC0" /* +++++ìü°°ì°+++ÿÀ */ + $"ECC0 ECC0 ECC0 FF00 0000 00FF 2B2B 2B2B" /* ìÀìÀìÀÿ....ÿ++++ */ + $"2B2B 2B2B 2BEC B0B0 B0EC B02B 2B2B 2BFF" /* +++++ì°°°ì°++++ÿ */ + $"C0EC C0EC C0FF 0000 0000 FF2B 2B2B 2B2B" /* ÀìÀìÀÿ....ÿ+++++ */ + $"2B2B 2B2B C0EC EC00 B0B0 EC2B 2B2B 2B2B" /* ++++Àìì.°°ì+++++ */ + $"FFC0 ECC0 FF00 0000 00FF 2B2B 2B2B 2B2B" /* ÿÀìÀÿ....ÿ++++++ */ + $"2B2B 2B2B 2BF9 B0F9 B0EC C02B 2B2B 2B2B" /* +++++ù°ù°ìÀ+++++ */ + $"2BFF C0FF 2BFF 0000 FF2B 2B2B 2B2B 2B2B" /* +ÿÀÿ+ÿ..ÿ+++++++ */ + $"2B2B 2B2B ECEC EC00 B0B0 EC2B 2B2B 2B2B" /* ++++ììì.°°ì+++++ */ + $"2B2B FF2B 2B2B FF00 00FF 2B2B 2B2B 2B2B" /* ++ÿ+++ÿ..ÿ++++++ */ + $"2B2B 2B2B ECEC B02B B0EC B02B 2B2B 2B2B" /* ++++ìì°+°ì°+++++ */ + $"2B2B 2B2B 2B2B 2BFF 0000 FF2B 2B2B 2B2B" /* +++++++ÿ..ÿ+++++ */ + $"2B2B 2B2B ECEC EC00 FCEC F92B 2B2B 2B2B" /* ++++ììì.üìù+++++ */ + $"2B2B 2B2B 2B2B FF00 0000 00FF 2B2B 2B2B" /* ++++++ÿ....ÿ++++ */ + $"2B2B 2B2B 2BEC B000 ECB0 EC2B 2B2B 2B2B" /* +++++ì°.ì°ì+++++ */ + $"2B2B 2B2B 2BFF 0000 0000 0000 FF2B 2B2B" /* +++++ÿ......ÿ+++ */ + $"2B2B 2B2B 2BEC FC2B B0FC 2B2B 2B2B 2B2B" /* +++++ìü+°ü++++++ */ + $"2B2B 2B2B FF00 0000 0000 0000 00FF 2B2B" /* ++++ÿ........ÿ++ */ + $"2B2B 2B2B 2BEC B000 B0EC EC2B 2B2B 2B2B" /* +++++ì°.°ìì+++++ */ + $"2B2B 2BFF 0000 0000 0000 0000 0000 FF2B" /* +++ÿ..........ÿ+ */ + $"2B2B 2B2B 2B2B B000 7FB0 2B2B 2B2B 2B2B" /* ++++++°..°++++++ */ + $"2B2B FF00 0000 0000 0000 0000 0000 00FF" /* ++ÿ............ÿ */ + $"2B2B 2B2B 2B2B B000 B0EC 2B2B 2B2B 2B2B" /* ++++++°.°ì++++++ */ + $"2BFF 0000 0000 0000 0000 0000 0000 0000" /* +ÿ.............. */ + $"FF2B 2B2B 2B2B F900 B02B 2B2B 2B2B 2B2B" /* ÿ+++++ù.°+++++++ */ + $"FF00 0000 0000 0000 0000 0000 0000 0000" /* ÿ............... */ + $"00FF 2B2B 2B2B F900 F92B 2B2B 2B2B 2BFF" /* .ÿ++++ù.ù++++++ÿ */ + $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ + $"0000 FF2B 2B2B F900 F92B 2B2B 2B2B FF00" /* ..ÿ+++ù.ù+++++ÿ. */ + $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ + $"0000 00FF 2B2B F900 F92B 2B2B 2BFF 0000" /* ...ÿ++ù.ù++++ÿ.. */ + $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ + $"0000 0000 FF2B 2B00 2B2B 2B2B FF00 0000" /* ....ÿ++.++++ÿ... */ + $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ + $"0000 0000 00FF 2BF9 2B2B 2BFF 0000 0000" /* .....ÿ+ù+++ÿ.... */ + $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ + $"0000 0000 0000 FF2B 2B2B FF00 0000 0000" /* ......ÿ+++ÿ..... */ + $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ + $"0000 0000 0000 00FF 2BFF 0000 0000 0000" /* .......ÿ+ÿ...... */ + $"0000 0000 0000 0000 0000 0000 0000 0000" /* ................ */ + $"0000 0000 0000 0000 FF00 0000 0000 0000" /* ........ÿ....... */ + $"0000 0000 0000 0000" /* ........ */ +}; diff --git a/macosx/tkAboutDlg.r b/macosx/tkAboutDlg.r new file mode 100644 index 0000000..13f0679 --- /dev/null +++ b/macosx/tkAboutDlg.r @@ -0,0 +1,393 @@ +/* + * 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. + * + * Copyright (c) 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: tkAboutDlg.r,v 1.2 2002/08/31 06:12:29 das Exp $ + */ + + + +/* + * New style DLOG templates have an extra field for the positioning + * options for the Dialog Box. We will not use this, for now, so we + * turn it off here. + */ + +#define DLOG_RezTemplateVersion 0 + +/* + * The folowing include and defines help construct + * the version string for Tcl. + */ + +#define RESOURCE_INCLUDED +#include <Carbon.r> +#include <tcl.h> +#include "tk.h" + +#if (TK_RELEASE_LEVEL == 0) +# define RELEASE_LEVEL alpha +#elif (TK_RELEASE_LEVEL == 1) +# define RELEASE_LEVEL beta +#elif (TK_RELEASE_LEVEL == 2) +# define RELEASE_LEVEL final +#endif + +#if (TK_RELEASE_LEVEL == 2) +# define MINOR_VERSION (TK_MINOR_VERSION * 16) + TK_RELEASE_SERIAL +#else +# define MINOR_VERSION TK_MINOR_VERSION * 16 +#endif + +#define RELEASE_CODE 0x00 + +/* + * 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 + * default dialog will not be shown and the Tcl procedure is expected to + * create and manage an About Dialog box. + */ + +data 'DLOG' (128, "Default About Box", purgeable) { + $"0055 006B 00F3 0196 0001 0100 0100 0000" + $"0000 0081 0000 280A" +}; + +resource 'DITL' (129, "About Box", purgeable) { + { + {128, 128, 148, 186}, Button {enabled, "Ok"}, + { 14, 108, 117, 298}, StaticText {disabled, + "Wish - Windowing Shell" "\n" "based on Tcl " + TCL_PATCH_LEVEL " & Tk " TK_PATCH_LEVEL "\n\n" "Jim Ingham & Ray Johnson" + "Scriptics Inc." "\n" "jingham@cygnus.com"}, + { 11, 24, 111, 92}, Picture {enabled, 128} + } +}; + +data 'PICT' (128, purgeable) { + $"13A4 0000 0000 0064 0044 0011 02FF 0C00" + $"FFFE 0000 0048 0000 0048 0000 0000 0000" + $"0064 0044 0000 0000 0001 000A 0000 0000" + $"0064 0044 0099 8044 0000 0000 0064 0044" + $"0000 0000 0000 0000 0048 0000 0048 0000" + $"0000 0008 0001 0008 0000 0000 0108 00D8" + $"0000 0000 0001 5A5A 8000 00FF 3736 FF00" + $"FF00 FF00 3535 FF00 FF00 CC00 3434 FF00" + $"FF00 9900 3333 FF00 FF00 6600 3736 FF00" + $"FF00 3300 3535 FF00 FF00 0000 3434 FF00" + $"CC00 FF00 3333 FF00 CC00 CC00 3736 FF00" + $"CC00 9900 3535 FF00 CC00 6600 FAFA FF00" + $"CC00 3300 3333 FF00 CC00 0000 3130 FF00" + $"9900 FF00 2F2F FF00 9900 CC00 FAFA FF00" + $"9900 9900 F9F9 FF00 9900 6600 3130 FF00" + $"9900 3300 2F2F FF00 9900 0000 2E2E FF00" + $"6600 FF00 F9F9 FF00 6600 CC00 3130 FF00" + $"6600 9900 2F2F FF00 6600 6600 2E2E FF00" + $"6600 3300 2D2D FF00 6600 0000 3130 FF00" + $"3300 FF00 2F2F FF00 3300 CC00 2E2E FF00" + $"3300 9900 2D2D FF00 3300 6600 3130 FF00" + $"3300 3300 2F2F FF00 3300 0000 2E2E FF00" + $"0000 FF00 2D2D FF00 0000 CC00 3130 FF00" + $"0000 9900 2F2F FF00 0000 6600 2E2E FF00" + $"0000 3300 2DF8 FF00 0000 0000 2B2A CC00" + $"FF00 FF00 2929 CC00 FF00 CC00 2828 CC00" + $"FF00 9900 27F8 CC00 FF00 6600 2B2A CC00" + $"FF00 3300 2929 CC00 FF00 0000 2828 CC00" + $"CC00 FF00 2727 CC00 CC00 CC00 2B2A CC00" + $"CC00 9900 2929 CC00 CC00 6600 2828 CC00" + $"CC00 3300 2727 CC00 CC00 0000 2B2A CC00" + $"9900 FF00 2929 CC00 9900 CC00 2828 CC00" + $"9900 9900 2727 CC00 9900 6600 DBDB CC00" + $"9900 3300 4747 CC00 9900 0000 4646 CC00" + $"6600 FF00 4545 CC00 6600 CC00 DBDB CC00" + $"6600 9900 4747 CC00 6600 6600 4646 CC00" + $"6600 3300 4545 CC00 6600 0000 DBDB CC00" + $"3300 FF00 4747 CC00 3300 CC00 4646 CC00" + $"3300 9900 4545 CC00 3300 6600 DBDB CC00" + $"3300 3300 4141 CC00 3300 0000 4040 CC00" + $"0000 FF00 3F3F CC00 0000 CC00 4342 CC00" + $"0000 9900 4141 CC00 0000 6600 4040 CC00" + $"0000 3300 3F3F CC00 0000 0000 4342 9900" + $"FF00 FF00 4141 9900 FF00 CC00 4040 9900" + $"FF00 9900 3F3F 9900 FF00 6600 4342 9900" + $"FF00 3300 4141 9900 FF00 0000 4040 9900" + $"CC00 FF00 3F3F 9900 CC00 CC00 4342 9900" + $"CC00 9900 4141 9900 CC00 6600 4040 9900" + $"CC00 3300 3F3F 9900 CC00 0000 4342 9900" + $"9900 FF00 4141 9900 9900 CC00 4040 9900" + $"9900 9900 3F3F 9900 9900 6600 3D3C 9900" + $"9900 3300 3B3B 9900 9900 0000 3A3A 9900" + $"6600 FF00 3939 9900 6600 CC00 3D3C 9900" + $"6600 9900 3B3B 9900 6600 6600 3A3A 9900" + $"6600 3300 3939 9900 6600 0000 3D3C 9900" + $"3300 FF00 3B3B 9900 3300 CC00 3A3A 9900" + $"3300 9900 3939 9900 3300 6600 3D3C 9900" + $"3300 3300 3B3B 9900 3300 0000 3A3A 9900" + $"0000 FF00 3939 9900 0000 CC00 3D3C 9900" + $"0000 9900 3B3B 9900 0000 6600 3A3A 9900" + $"0000 3300 3939 9900 0000 0000 3D3C 6600" + $"FF00 FF00 3B3B 6600 FF00 CC00 3A3A 6600" + $"FF00 9900 3939 6600 FF00 6600 3D3C 6600" + $"FF00 3300 3B3B 6600 FF00 0000 3A3A 6600" + $"CC00 FF00 3939 6600 CC00 CC00 3736 6600" + $"CC00 9900 3535 6600 CC00 6600 3434 6600" + $"CC00 3300 3333 6600 CC00 0000 3736 6600" + $"9900 FF00 3535 6600 9900 CC00 3434 6600" + $"9900 9900 3333 6600 9900 6600 3736 6600" + $"9900 3300 3535 6600 9900 0000 3434 6600" + $"6600 FF00 3333 6600 6600 CC00 3736 6600" + $"6600 9900 3535 6600 6600 6600 3434 6600" + $"6600 3300 3333 6600 6600 0000 3736 6600" + $"3300 FF00 3535 6600 3300 CC00 3434 6600" + $"3300 9900 3333 6600 3300 6600 3736 6600" + $"3300 3300 3535 6600 3300 0000 3434 6600" + $"0000 FF00 3333 6600 0000 CC00 3130 6600" + $"0000 9900 2F2F 6600 0000 6600 2E2E 6600" + $"0000 3300 F9F9 6600 0000 0000 3130 3300" + $"FF00 FF00 2F2F 3300 FF00 CC00 2E2E 3300" + $"FF00 9900 F9F9 3300 FF00 6600 3130 3300" + $"FF00 3300 2F2F 3300 FF00 0000 2E2E 3300" + $"CC00 FF00 2D2D 3300 CC00 CC00 3130 3300" + $"CC00 9900 2F2F 3300 CC00 6600 2E2E 3300" + $"CC00 3300 2D2D 3300 CC00 0000 3130 3300" + $"9900 FF00 2F2F 3300 9900 CC00 2E2E 3300" + $"9900 9900 2D2D 3300 9900 6600 3130 3300" + $"9900 3300 2F2F 3300 9900 0000 2E2E 3300" + $"6600 FF00 2DF8 3300 6600 CC00 2B2A 3300" + $"6600 9900 2929 3300 6600 6600 2828 3300" + $"6600 3300 27F8 3300 6600 0000 2B2A 3300" + $"3300 FF00 2929 3300 3300 CC00 2828 3300" + $"3300 9900 2727 3300 3300 6600 2B2A 3300" + $"3300 3300 2929 3300 3300 0000 2828 3300" + $"0000 FF00 2727 3300 0000 CC00 2B2A 3300" + $"0000 9900 2929 3300 0000 6600 2828 3300" + $"0000 3300 2727 3300 0000 0000 4948 0000" + $"FF00 FF00 4747 0000 FF00 CC00 4646 0000" + $"FF00 9900 4545 0000 FF00 6600 4948 0000" + $"FF00 3300 4747 0000 FF00 0000 4646 0000" + $"CC00 FF00 4545 0000 CC00 CC00 4948 0000" + $"CC00 9900 4747 0000 CC00 6600 4646 0000" + $"CC00 3300 4545 0000 CC00 0000 4342 0000" + $"9900 FF00 4141 0000 9900 CC00 4040 0000" + $"9900 9900 3F3F 0000 9900 6600 4342 0000" + $"9900 3300 4141 0000 9900 0000 4040 0000" + $"6600 FF00 3F3F 0000 6600 CC00 4342 0000" + $"6600 9900 4141 0000 6600 6600 4040 0000" + $"6600 3300 3F3F 0000 6600 0000 4342 0000" + $"3300 FF00 4141 0000 3300 CC00 4040 0000" + $"3300 9900 3F3F 0000 3300 6600 4342 0000" + $"3300 3300 4141 0000 3300 0000 4040 0000" + $"0000 FF00 3F3F 0000 0000 CC00 4342 0000" + $"0000 9900 4141 0000 0000 6600 4040 0000" + $"0000 3300 3F3F EE00 0000 0000 3D3C DD00" + $"0000 0000 3B3B BB00 0000 0000 3A3A AA00" + $"0000 0000 3939 8800 0000 0000 3D3C 7700" + $"0000 0000 3B3B 5500 0000 0000 3A3A 4400" + $"0000 0000 3939 2200 0000 0000 3D3C 1100" + $"0000 0000 3B3B 0000 EE00 0000 3A3A 0000" + $"DD00 0000 3939 0000 BB00 0000 3D3C 0000" + $"AA00 0000 3B3B 0000 8800 0000 3A3A 0000" + $"7700 0000 3939 0000 5500 0000 3D3C 0000" + $"4400 0000 3B3B 0000 2200 0000 3A3A 0000" + $"1100 0000 3939 0000 0000 EE00 3D3C 0000" + $"0000 DD00 3B3B 0000 0000 BB00 3A3A 0000" + $"0000 AA00 3939 0000 0000 8800 3D3C 0000" + $"0000 7700 3B3B 0000 0000 5500 3A3A 0000" + $"0000 4400 3939 0000 0000 2200 3736 0000" + $"0000 1100 3535 EE00 EE00 EE00 3434 DD00" + $"DD00 DD00 3333 BB00 BB00 BB00 3736 AA00" + $"AA00 AA00 3535 8800 8800 8800 3434 7700" + $"7700 7700 3333 5500 5500 5500 3736 4400" + $"4400 4400 3535 2200 2200 2200 3434 1100" + $"1100 1100 3333 0000 0000 0000 0000 0000" + $"0064 0044 0000 0000 0064 0044 0000 000A" + $"0000 0000 0064 0044 02BD 0013 E800 01F5" + $"F6FE 07FE 0E02 3232 33FD 3900 0EE6 001D" + $"FC00 01F5 F5FE 0700 08FE 0E02 3232 33FE" + $"3900 3AFC 40F2 4102 4033 07E9 0017 0100" + $"0EFC 40DC 4102 390E F5F5 0002 F5F5 F6FE" + $"0702 0E07 0016 0100 32D5 4104 4039 0E32" + $"33FD 3900 3AFC 40FC 4101 3200 0801 000E" + $"C141 010E 0008 0100 0EC1 4101 0800 0801" + $"000E C141 0107 0008 0100 0EC1 4101 0700" + $"0901 0007 C241 0240 F500 0E01 0007 E841" + $"0147 47DD 4102 4000 0012 0100 07F0 4100" + $"47FA 4101 3B3B DD41 0240 0000 1901 0007" + $"F141 0C47 3B0B 3B47 4141 4711 0505 3B47" + $"DF41 023A 0000 1701 00F6 F041 010B 0BFE" + $"4105 473B 0505 113B DE41 0239 0000 1A02" + $"00F5 40F3 410C 473B 053B 4741 4741 0B0B" + $"3B47 47DE 4102 3900 0018 0200 F540 F341" + $"0247 110B FE41 0447 1105 4147 DC41 0233" + $"0000 1B02 0000 40F3 4103 4711 1147 FE41" + $"0205 3547 F741 FD47 E941 0232 0000 1E02" + $"0000 40F2 4106 113B 4741 4735 0BF7 4106" + $"4741 390E 0E40 47EA 4102 0E00 0021 0200" + $"0040 F241 0711 3B47 4141 0B35 47F9 4102" + $"4740 07FE 0002 F640 47EB 4102 0E00 0023" + $"0200 0040 F341 0847 3541 4147 3B05 4147" + $"FA41 0947 3AF6 00F5 4F55 F50E 47EB 4102" + $"0700 0022 0200 003A F341 0147 3BFE 4101" + $"0B0B F941 0547 3AF5 0055 C8FE CE01 5640" + $"EB41 0207 0000 1F02 0000 39F0 4104 4741" + $"053B 47FB 4104 4740 F5F5 A4FC CE01 C85D" + $"EB41 02F6 0000 1F02 0000 39F0 4104 473B" + $"0541 47FC 4104 4740 07F6 C8FA CE00 64EC" + $"4103 40F5 0000 1C02 0000 39F0 4102 4711" + $"0BFA 4103 4708 2AC8 FACE 0164 D8EC 4100" + $"40FE 0025 0200 0039 EF41 020B 3B47 FC41" + $"0347 0FF5 A4FB CE02 C887 D8FC 41FE 47FC" + $"4100 47F9 4100 3AFE 0028 0200 0039 EF41" + $"020B 3B47 FD41 0347 3900 A4FA CE00 ABFA" + $"4109 3B11 3B41 4147 3B0B 3B47 FA41 0039" + $"FE00 2402 0000 33F1 4102 4741 0BFA 4101" + $"0779 F9CE 0064 FA41 0235 050B FD41 010B" + $"0BF9 4100 39FE 0028 0200 0032 F141 0247" + $"3B0B FC41 0247 39F6 F9CE 0187 D8FB 4103" + $"4741 050B FE41 0247 110B F941 0039 FE00" + $"2C02 0000 32F1 4102 473B 11FB 4101 0879" + $"FACE 05AA 4041 4147 47FE 410A 4741 0511" + $"4741 4147 3511 47FA 4100 32FE 002F 0200" + $"000E F141 0347 3B11 47FE 4103 4740 F6C8" + $"FACE 0564 D841 4039 39FE 4104 473B 053B" + $"47FE 4102 3541 47FA 4100 0EFE 0027 0200" + $"000E F141 0347 3B3B 47FE 4102 470F 79FA" + $"CE0C 8741 4032 F500 003A 4741 473B 05F2" + $"4100 0EFE 0027 0200 000E F141 0347 3B3B" + $"47FD 4101 0EA4 FACE 01AB AAFE C808 7900" + $"3947 4147 110B 47F3 4100 07FE 001C 0200" + $"000E EA41 0240 2BC8 F5CE 0881 0033 4741" + $"410B 3B47 F341 0007 FE00 1A02 0000 08EB" + $"4102 473A 55F4 CE06 5D00 3947 4741 0BF1" + $"4100 F6FE 001C 0200 0007 EB41 0247 3979" + $"F4CE 0739 0039 4747 3511 47F3 4101 40F5" + $"FE00 1C02 0000 07EB 4102 4739 A4F5 CE08" + $"AB0E 0040 4741 1141 47F3 4100 40FD 001B" + $"0200 0007 EB41 0247 39A4 F5CE 0787 0707" + $"4147 4111 47F2 4100 40FD 001B 0200 0007" + $"EB41 0247 39C8 F5CE 0763 F532 4747 3B3B" + $"47F2 4100 3AFD 001A 0300 00F6 40EC 4102" + $"4739 C8F5 CE05 39F5 4047 413B F041 0039" + $"FD00 1C03 0000 F540 EB41 0140 C8FD CE01" + $"C8A4 FCCE 03AB 080E 47ED 4100 39FD 001A" + $"FE00 0040 EB41 0040 FCCE 01A4 C8FC CE03" + $"FA07 4047 ED41 0032 FD00 1AFE 0000 40EA" + $"4100 AAFE CE02 87F9 C8FC CE02 560F 47EC" + $"4100 32FD 0019 FE00 0040 EA41 00AB FECE" + $"0264 56C8 FDCE 01C8 32EA 4100 0EFD 001B" + $"FE00 0040 ED41 030E 4047 87FE CE01 4055" + $"FCCE 01FA 40EA 4100 08FD 001A FE00 003A" + $"ED41 0807 0740 FBCE CEAB 3979 FDCE 00AB" + $"E841 0007 FD00 1CFE 0000 3AED 4108 0700" + $"F6A4 CECE 8733 79FD CE02 4147 47EA 4100" + $"07FD 001E FE00 0039 ED41 0807 2AA4 C8CE" + $"CE88 0E9D FECE 0364 1C39 39EB 4101 40F5" + $"FD00 1CFE 0000 39ED 4101 074F FDCE 0264" + $"F7A4 FECE 03AB 80F6 07EB 4100 40FC 001C" + $"FE00 0039 ED41 0108 79FE CE03 AB40 2BA4" + $"FCCE 02F7 0E47 EC41 0040 FC00 1CFE 0000" + $"39ED 4101 0879 FECE 03AB 40F6 C8FC CE02" + $"F615 47EC 4100 40FC 001E FE00 003A EE41" + $"0247 0E79 FECE 03AB 40F5 C8FD CE03 A4F5" + $"3A47 EC41 0040 FC00 1EFE 0000 3AEE 4102" + $"470E 56FE CE03 FB3A F6C8 FDCE 0280 F540" + $"EB41 0140 F5FD 001E FE00 0040 EE41 0947" + $"0F56 CECE C888 39F6 C8FD CE02 5601 40EB" + $"4101 40F5 FD00 1CFE 0000 40EE 4109 4739" + $"32CE CEC8 8839 2AC8 FDCE 0156 07E9 4100" + $"F6FD 001B FE00 0040 EE41 0847 3A32 CECE" + $"C864 152A FCCE 0132 07E9 4100 07FD 001A" + $"FE00 0040 ED41 0740 32AB CEC8 6439 4EFC" + $"CE01 3A07 E941 0007 FD00 1D03 0000 F540" + $"ED41 0740 0EAB CECE 640F 4EFD CE03 AB40" + $"0840 EA41 0007 FD00 1B03 0000 F540 EC41" + $"060F 81CE CE64 334E FDCE 02AB 400E E941" + $"000E FD00 1C02 0000 F6EC 4107 4715 FACE" + $"CE64 334E FDCE 0387 0F0E 47EA 4100 0EFD" + $"001C 0200 0007 EC41 0747 16F9 CEC8 6433" + $"4EFD CE03 6308 4047 EA41 000E FD00 1A02" + $"0000 07EB 4106 40F9 CEC8 6439 4EFD CE02" + $"3940 47E9 4100 32FD 001B 0200 0007 EA41" + $"0539 CECE 8839 F6FE CE04 AB41 4139 40EA" + $"4100 32FD 001C 0200 0007 EB41 0E47 3AC8" + $"CE88 39F6 C8CE CE64 15F6 F540 EA41 0033" + $"FD00 1A02 0000 07EA 410C 40A4 CE87 392A" + $"C8CE AB41 40F8 F6E9 4100 39FD 001B 0200" + $"000E EB41 0D47 41AB C887 39F5 C8CE ABAB" + $"CEA4 07E9 4100 39FD 001C 0200 000E ED41" + $"0947 3939 4787 C8AB 40F5 C8FD CE01 A40E" + $"E941 0039 FD00 1D02 0000 0EED 4109 473A" + $"0007 80CE AB40 F5C8 FDCE 0255 0E47 EA41" + $"0039 FD00 1B02 0000 0EEB 4107 0779 C8CE" + $"CE40 F6A4 FDCE 022B 3947 EA41 003A FD00" + $"1C02 0000 0EEC 4102 4739 79FE CE02 6407" + $"A4FE CE02 A407 40E9 4100 40FD 001A 0200" + $"0032 EA41 0632 A4CE CE88 0879 FECE 02F9" + $"0F47 E941 0040 FD00 1A02 0000 32EB 4107" + $"4740 F7C8 CE87 0E79 FECE 0132 40E8 4100" + $"40FD 0019 0200 0033 EA41 0B47 40F8 C8AB" + $"0E55 CECE 8015 47E8 4100 40FD 0017 0200" + $"0033 E941 0847 40F9 A439 4FCE CE5D E641" + $"0140 F5FE 0014 0200 0039 E841 0647 64FB" + $"392B C8AB E441 00F6 FE00 1102 0000 39E5" + $"4103 40F6 8764 E441 0007 FE00 1E02 0000" + $"39EB 4102 3A0E 0EFD 4102 0740 47F6 4104" + $"400F 0839 47F4 4100 07FE 0027 0200 0039" + $"FB41 0147 47F2 4102 0800 40FE 4102 0839" + $"47FC 4101 4747 FC41 0339 0039 47F4 4100" + $"07FE 0029 0200 0039 FB41 0140 39F3 4109" + $"470E F540 4141 470E 3347 FC41 0139 3AFD" + $"4104 4739 0039 47F4 4100 08FE 0036 0200" + $"003A FC41 0347 0E00 40FC 4102 4741 40FC" + $"4109 470E F540 4141 4733 0E47 FE41 0447" + $"4000 0E47 FE41 0447 3900 3941 FE40 F741" + $"000E FE00 3A02 0000 3AFD 410E 4740 0700" + $"0E40 4741 4147 390E 390E 40FE 4108 470E" + $"F540 4141 4739 0EFC 4103 0F00 0739 FE41" + $"0747 3900 3940 080F 39F7 4100 0EFE 0035" + $"0200 0040 FB41 020E 0040 FE41 0D47 4000" + $"3941 0032 4741 4147 0EF5 40FE 4101 4008" + $"FC41 023A 000E FD41 0547 3900 3939 33F5" + $"4100 0EFE 0039 0200 0040 FC41 0347 0E00" + $"40FE 4106 4732 0040 4139 40FE 4103 470E" + $"F540 FD41 0108 40FE 4104 4740 000E 47FE" + $"4106 4739 0007 F540 47F6 4100 32FE 003A" + $"0200 0040 FC41 0C47 0E00 4047 4141 470E" + $"0040 4747 FD41 0347 0EF5 40FE 410A 470E" + $"3947 4141 4740 000E 47FE 4107 4739 000E" + $"0007 4147 F741 0032 FE00 3802 0000 40FC" + $"4102 470E 00FD 4106 4739 003A 4740 39FE" + $"4102 470E F5FD 410A 4733 3347 4141 4740" + $"000E 47FE 4106 4739 0039 3900 0EF6 4100" + $"33FE 003A 0200 F540 FC41 0447 3200 0E39" + $"FD41 0B0E 0E40 333A 4741 413A 07F5 39FE" + $"4102 473A 0EFD 410F 40F5 0733 4041 4140" + $"0E00 0E40 0700 0E40 F841 0039 FE00 2902" + $"00F5 40FA 4101 3939 FB41 023A 3A40 FD41" + $"FD40 FD41 0240 0E40 FD41 0240 3940 FD41" + $"FA40 F741 0039 FE00 2A01 00F6 F941 0147" + $"47FB 4101 4747 FB41 0147 47FB 4101 3940" + $"FD41 0147 47FB 4100 47FE 4100 47F6 4100" + $"39FE 000D 0100 07E1 4100 40E4 4100 3AFE" + $"0009 0100 07C3 4100 3AFE 0009 0100 07C3" + $"4100 40FE 0009 0100 07C3 4100 40FE 0009" + $"0100 07C3 4100 40FE 000A 0100 0EC3 4103" + $"40F5 0000 0901 000E C241 02F6 0000 0901" + $"000E C241 0207 0000 0901 000E C241 0207" + $"0000 1101 000E ED41 FE40 003A F940 E241" + $"0207 0000 2B01 0032 F941 FE40 FE39 0632" + $"0E0E 0707 F6F5 F800 02F5 F5F6 FB07 FB0E" + $"0332 3233 33FB 3901 3A3A FB40 0207 0000" + $"0E0A 000E 3939 320E 0E07 07F6 F5C8 0002" + $"BD00 00FF" +}; diff --git a/macosx/tkMacOSX.h b/macosx/tkMacOSX.h new file mode 100644 index 0000000..45bbf7b --- /dev/null +++ b/macosx/tkMacOSX.h @@ -0,0 +1,34 @@ +/* + * tkMacOSXInt.h -- + * + * Declarations of Macintosh specific exported variables and procedures. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * 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.2 2002/08/31 06:12:29 das Exp $ + */ + +#ifndef _TKMAC +#define _TKMAC + +#include <Carbon/Carbon.h> +#include "tkInt.h" + +/* + * 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 void (Tk_MacOSXEmbedGetOffsetInParentProc) (Tk_Window window, Point *ulCorner); + +#include "tkPlatDecls.h" + +#endif /* _TKMAC */ diff --git a/macosx/tkMacOSXAppInit.c b/macosx/tkMacOSXAppInit.c new file mode 100644 index 0000000..422546b --- /dev/null +++ b/macosx/tkMacOSXAppInit.c @@ -0,0 +1,241 @@ +/* + * tkAppInit.c -- + * + * Provides a default version of the Tcl_AppInit procedure for + * use in wish and similar Tk-based applications. + * + * Copyright (c) 1993 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkMacOSXAppInit.c,v 1.2 2002/08/31 06:12:29 das Exp $ + */ +#include <pthread.h> +#include "tk.h" +#include "tclInt.h" +#include "locale.h" + +#include <Carbon/Carbon.h> +#include "tkMacOSX.h" +#include "tkMacOSXEvent.h" + +#ifndef MAX_PATH_LEN + #define MAX_PATH_LEN 1024 +#endif + +/* + * If the App is in an App package, then we want to add the Scripts + * directory to the auto_path. But we have to wait till after the + * Tcl_Init is run, or it gets blown away. This stores what we + * figured out in main. + */ + +char scriptPath[MAX_PATH_LEN + 1]; + +extern Tcl_Interp *gStdoutInterp; + +#ifdef TK_TEST +extern int Tktest_Init _ANSI_ARGS_((Tcl_Interp *interp)); +#endif /* TK_TEST */ + +/* + *---------------------------------------------------------------------- + * + * main -- + * + * This is the main program for the application. + * + * Results: + * None: Tk_Main never returns here, so this procedure never + * returns either. + * + * Side effects: + * Whatever the application does. + * + *---------------------------------------------------------------------- + */ + +int +main(argc, argv) + int argc; /* Number of command-line arguments. */ + char **argv; /* Values of command-line arguments. */ +{ + int textEncoding; /* + * Variable used to take care of + * lazy font initialization + */ + CFBundleRef bundleRef; + + /* + * The following #if block allows you to change the AppInit + * function by using a #define of TCL_LOCAL_APPINIT instead + * of rewriting this entire file. The #if checks for that + * #define and uses Tcl_AppInit if it doesn't exist. + */ + +#ifndef TK_LOCAL_APPINIT +#define TK_LOCAL_APPINIT Tcl_AppInit +#endif + extern int TK_LOCAL_APPINIT _ANSI_ARGS_((Tcl_Interp *interp)); + + scriptPath[0] = '\0'; + + /* + * The following #if block allows you to change how Tcl finds the startup + * script, prime the library or encoding paths, fiddle with the argv, + * etc., without needing to rewrite Tk_Main(). Note, if you use this + * hook, then I won't do the CFBundle lookup, since if you are messing + * around at this level, you probably don't want me to do this for you... + */ + +#ifdef TK_LOCAL_MAIN_HOOK + extern int TK_LOCAL_MAIN_HOOK _ANSI_ARGS_((int *argc, char ***argv)); + TK_LOCAL_MAIN_HOOK(&argc, &argv); +#else + + /* + * 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. + */ + + bundleRef = CFBundleGetMainBundle(); + + if (bundleRef != NULL) { + CFURLRef appMainURL; + appMainURL = CFBundleCopyResourceURL(bundleRef, + CFSTR("AppMain"), + CFSTR("tcl"), + CFSTR("Scripts")); + + if (appMainURL != NULL) { + CFURLRef scriptFldrURL; + char *startupScript = malloc(MAX_PATH_LEN + 1); + + if (CFURLGetFileSystemRepresentation (appMainURL, true, + startupScript, MAX_PATH_LEN)) { + TclSetStartupScriptFileName(startupScript); + scriptFldrURL = CFBundleCopyResourceURL(bundleRef, + CFSTR("Scripts"), + NULL, + NULL); + CFURLGetFileSystemRepresentation(scriptFldrURL, + true, scriptPath, MAX_PATH_LEN); + CFRelease(scriptFldrURL); + } else { + free(startupScript); + } + CFRelease(appMainURL); + } + } + +#endif + textEncoding=GetApplicationTextEncoding(); + + /* + * Now add the scripts folder to the auto_path. + */ + + Tk_Main(argc,argv,TK_LOCAL_APPINIT); + return 0; /* Needed only to prevent compiler warning. */ +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_AppInit -- + * + * This procedure performs application-specific initialization. + * Most applications, especially those that incorporate additional + * packages, will have their own version of this procedure. + * + * Results: + * Returns a standard Tcl completion code, and leaves an error + * message in the interp's result if an error occurs. + * + * Side effects: + * Depends on the startup script. + * + *---------------------------------------------------------------------- + */ + +int +Tcl_AppInit(interp) + Tcl_Interp *interp; /* Interpreter for application. */ +{ + if (Tcl_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + if (Tk_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + Tcl_StaticPackage(interp, "Tk", Tk_Init, Tk_SafeInit); + + if (scriptPath[0] != '\0') { + Tcl_SetVar(interp, "auto_path", scriptPath, + TCL_GLOBAL_ONLY|TCL_LIST_ELEMENT|TCL_APPEND_VALUE); + } + +#ifdef TK_TEST + if (Tktest_Init(interp) == TCL_ERROR) { + return TCL_ERROR; + } + Tcl_StaticPackage(interp, "Tktest", Tktest_Init, + (Tcl_PackageInitProc *) NULL); +#endif /* TK_TEST */ + + /* + * If we don't have a TTY, then use the Tk based console + * interpreter instead. + */ + + if (ttyname(0) == NULL) { + Tk_InitConsoleChannels(interp); + Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDIN)); + Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDOUT)); + Tcl_RegisterChannel(interp, Tcl_GetStdChannel(TCL_STDERR)); + if (Tk_CreateConsoleWindow(interp) == TCL_ERROR) { + goto error; + } + /* Only show the console if we don't have a startup script */ + if (TclGetStartupScriptPath() == NULL) { + Tcl_Eval(interp, "console show"); + } + } + + /* + * Call the init procedures for included packages. Each call should + * look like this: + * + * if (Mod_Init(interp) == TCL_ERROR) { + * return TCL_ERROR; + * } + * + * where "Mod" is the name of the module. + */ + + /* + * Call Tcl_CreateCommand for application-specific commands, if + * they weren't already created by the init procedures called above. + */ + + + /* + * Specify a user-specific startup file to invoke if the application + * is run interactively. Typically the startup file is "~/.apprc" + * where "app" is the name of the application. If this line is deleted + * then no user-specific startup file will be run under any conditions. + */ + + Tcl_SetVar(interp, "tcl_rcFileName", "~/.wishrc", TCL_GLOBAL_ONLY); + + return TCL_OK; + + error: + return TCL_ERROR; +} diff --git a/macosx/tkMacOSXApplication.r b/macosx/tkMacOSXApplication.r new file mode 100644 index 0000000..0012f29 --- /dev/null +++ b/macosx/tkMacOSXApplication.r @@ -0,0 +1,276 @@ +/* + * tkMacOSXApplication.r -- + * + * This file creates resources for use in the Wish application. + * + * Copyright (c) 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: tkMacOSXApplication.r,v 1.2 2002/08/31 06:12:29 das Exp $ + */ + +#include <Carbon/Carbon.r> + +/* + * The folowing include and defines help construct + * the version string for Tcl. + */ + +#define RESOURCE_INCLUDED +#include "tk.h" + +#if (TK_RELEASE_LEVEL == 0) +# define RELEASE_LEVEL alpha +#elif (TK_RELEASE_LEVEL == 1) +# define RELEASE_LEVEL beta +#elif (TK_RELEASE_LEVEL == 2) +# define RELEASE_LEVEL final +#endif + +#if (TK_RELEASE_LEVEL == 2) +# define MINOR_VERSION (TK_MINOR_VERSION * 16) + TK_RELEASE_SERIAL +#else +# define MINOR_VERSION TK_MINOR_VERSION * 16 +#endif + +#define RELEASE_CODE 0x00 + +resource 'vers' (1) { + TK_MAJOR_VERSION, MINOR_VERSION, + RELEASE_LEVEL, 0x00, verUS, + TK_PATCH_LEVEL, + TK_PATCH_LEVEL ", by Jim Ingham & Ian Reid" "\n" "© 2001 Apple Computer, Inc" "\n" "1998-2000 Scriptics Inc." "\n" "1996-1997 Sun Microsystems Inc." +}; + +resource 'vers' (2) { + TK_MAJOR_VERSION, MINOR_VERSION, + RELEASE_LEVEL, 0x00, verUS, + TK_PATCH_LEVEL, + "Wish " TK_PATCH_LEVEL " © 1993-1999" +}; + +#define TK_APP_RESOURCES 128 +#define TK_APP_CREATOR 'WIsH' + +/* + * The 'BNDL' resource is the primary link between a file's + * creator/type and its icon. This resource acts for all Tcl shared + * libraries; other libraries will not need one and ought to use + * custom icons rather than new file types for a different appearance. + */ + +resource 'BNDL' (TK_APP_RESOURCES, "Tk app bundle", purgeable) +{ + TK_APP_CREATOR, + 0, + { + 'FREF', + { + 0, TK_APP_RESOURCES, + 1, TK_APP_RESOURCES+1 + }, + 'ICN#', + { + 0, TK_APP_RESOURCES, + 1, TK_APP_RESOURCES+1 + } + } +}; + +resource 'FREF' (TK_APP_RESOURCES, purgeable) +{ + 'APPL', 0, "" +}; +resource 'FREF' (TK_APP_RESOURCES+1, purgeable) +{ + 'TEXT', 1, "" +}; + +type TK_APP_CREATOR as 'STR '; +resource TK_APP_CREATOR (0, purgeable) { + "Wish " TK_PATCH_LEVEL " © 1996" +}; + +/* + * The 'kind' resource works with a 'BNDL' in Macintosh Easy Open + * to affect the text the Finder displays in the "kind" column and + * file info dialog. This information will be applied to all files + * with the listed creator and type. + */ +resource 'kind' (TK_APP_RESOURCES, "Tcl kind", purgeable) { + TK_APP_CREATOR, + 0, /* region = USA */ + { + 'APPL', "Wish", + 'TEXT', "Tcl/Tk Script" + } +}; + +#define kIconHelpString 256 + +resource 'hfdr' (-5696, purgeable) { + HelpMgrVersion, hmDefaultOptions, 0, 0, + {HMSTRResItem {kIconHelpString}} +}; +resource 'STR ' (kIconHelpString, purgeable) { + "This is the interpreter for Tcl & Tk scripts" + " running on Macintosh computers." +}; + +/* + * The following resource define the icon used by Tcl scripts. Any + * TEXT file with the creator of WIsH will get this icon. + */ + +data 'icl4' (TK_APP_RESOURCES + 1, "Tk Doc", purgeable) { + $"000F FFFF FFFF FFFF FFFF FFF0 0000 0000" + $"000F 3333 3333 3333 3333 33FF 0000 0000" + $"000F 3333 3333 3333 3433 33F2 F000 0000" + $"000F 3333 3333 3333 7D43 33F2 2F00 0000" + $"000F 3333 3333 3335 5623 33F2 22F0 0000" + $"000F 3333 3333 3356 6343 33FF FFFF 0000" + $"000F 3333 3333 256F 5223 3333 333F 0000" + $"000F 3333 3333 D666 2433 3333 333F 0000" + $"000F 3333 3333 D5F6 6633 3333 333F 0000" + $"000F 3333 3332 5666 6733 3333 333F 0000" + $"000F 3333 3336 E56F 6633 3333 333F 0000" + $"000F 3333 3336 5656 5733 3333 333F 0000" + $"000F 3333 3336 E5B6 5233 3333 333F 0000" + $"000F 3333 3336 5ED6 3333 3333 333F 0000" + $"000F 3333 3376 6475 6233 3333 333F 0000" + $"000F 3333 333D 5D56 7333 3333 333F 0000" + $"000F 3333 3336 6C55 6333 3333 333F 0000" + $"000F 3333 3336 5C56 7333 3333 333F 0000" + $"000F 3333 3362 6CE6 D333 3333 333F 0000" + $"000F 3333 3336 5C65 6333 3333 333F 0000" + $"000F 3333 3336 EC5E 3333 3333 333F 0000" + $"000F 3333 3336 5C56 6333 3333 333F 0000" + $"000F 3333 3333 5C75 3333 3333 333F 0000" + $"000F 3333 3333 5DD6 3333 3333 333F 0000" + $"000F 3333 3333 3CDD 3333 3333 333F 0000" + $"000F 3333 3333 3303 3333 3333 333F 0000" + $"000F 3333 3333 3C33 3333 3333 333F 0000" + $"000F 3333 3333 3C33 3333 3333 333F 0000" + $"000F 3333 3333 3C33 3333 3333 333F 0000" + $"000F 3333 3333 3333 3333 3333 333F 0000" + $"000F 3333 3333 3333 3333 3333 333F 0000" + $"000F FFFF FFFF FFFF FFFF FFFF FFFF 0000" +}; + +data 'ICN#' (TK_APP_RESOURCES + 1, "Tk Doc", purgeable) { + $"1FFF FE00 1000 0300 1000 F280 1003 F240" + $"1003 E220 1007 E3F0 100F C010 100F C010" + $"100F C010 101F F010 101F F010 101F F010" + $"101F F010 101F F010 101D E010 101D E010" + $"101D E010 101D C010 101D C010 101D C010" + $"101D C010 100D 8010 100D 8010 100D 8010" + $"1005 8010 1002 0010 1002 0010 1002 0010" + $"1002 0010 1002 0010 1000 0010 1FFF FFF0" + $"1FFF FE00 1FFF FF00 1FFF FF80 1FFF FFC0" + $"1FFF FFE0 1FFF FFF0 1FFF FFF0 1FFF FFF0" + $"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0" + $"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0" + $"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0" + $"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0" + $"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0" + $"1FFF FFF0 1FFF FFF0 1FFF FFF0 1FFF FFF0" +}; + +data 'ics#' (TK_APP_RESOURCES + 1, "Tk Doc", purgeable) { + $"7FF0 41D8 419C 4384 43C4 47C4 47C4 4784" + $"4684 4684 4284 4284 4104 4104 4104 7FFC" + $"7FE0 7FF0 7FF8 7FFC 7FFC 7FFC 7FFC 7FFC" + $"7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC" +}; + +data 'ics4' (TK_APP_RESOURCES + 1, "Tk Doc", purgeable) { + $"0FFF FFFF FFFF 0000 0F33 3333 53F2 F000" + $"0F33 3335 52FF FF00 0F33 33E6 3333 3F00" + $"0F33 3256 6333 3F00 0F33 3556 6333 3F00" + $"0F33 3A5E 3333 3F00 0F33 65D6 D333 3F00" + $"0F33 3655 5333 3F00 0F33 65C6 3333 3F00" + $"0F33 3EC5 E333 3F00 0F33 36C6 3333 3F00" + $"0F33 33CD 3333 3F00 0F33 33C3 3333 3F00" + $"0F33 33C3 3333 3F00 0FFF FFFF FFFF FF00" +}; + +/* + * The following resources define the icons for the Wish + * application. + */ + +data 'icl4' (TK_APP_RESOURCES, "Tk App", purgeable) { + $"0000 0000 0000 000F 0000 0000 0000 0000" + $"0000 0000 0000 00FC F000 0000 0000 0000" + $"0000 0000 0000 0FCC CF66 0000 0000 0000" + $"0000 0000 0000 FCCC C556 0000 0000 0000" + $"0000 0000 000F CCCC 566F 0000 0000 0000" + $"0000 0000 00FC CCC5 6F5C F000 0000 0000" + $"0000 0000 0FCC CC66 66CC CF00 0000 0000" + $"0000 0000 FCCC CCD5 5666 CCF0 0000 0000" + $"0000 000F CCCC C656 5667 CCCF 0000 0000" + $"0000 00FC CCCC C6E5 5566 CCCC F000 0000" + $"0000 0FCC CCCC C656 5657 CCCC CF00 0000" + $"0000 FCCC CCCC C6E5 565C CCCC CCF0 0000" + $"000F CCCC CCCC C655 565C CCCC CCCF 0000" + $"00FC CCCC CCCC 7660 556C CCCC CCCC F000" + $"0FCC CCCC CCCC CD5D 567C CCCC CCCC CF00" + $"FCCC CCCC CCCC 6660 556C CCCC CCCC CCF0" + $"0FCC CCCC CCCC 665C 565C CCCC CCCC C0CF" + $"00FC CCCC CCCC 6660 E6DC CCCC CCCC CCF0" + $"000F CCCC CCCC C650 656C CCCC CCCC CF00" + $"0000 FCCC CCCC C6EC 5ECC CCCC CCCC F000" + $"0000 0FCC CCCC C650 566C CCCC CCCF 0000" + $"0000 00FC CCCC CC50 75CC CCCC CCF0 0000" + $"0000 000F CCCC CC50 56CC CCCC CF00 0000" + $"0000 0000 FCCC CCC0 5CCC CCCC F000 0000" + $"0000 0000 0FCC CCC0 CCCC CCCF 0000 0000" + $"0000 0000 00FC CCC0 CCCC CCF0 0000 0000" + $"0000 0000 000F CCC0 CCCC CF00 0000 0000" + $"0000 0000 0000 FCCC CCCC F000 0000 0000" + $"0000 0000 0000 0FCC CCCF 0000 0000 0000" + $"0000 0000 0000 00FC CCF0 0000 0000 0000" + $"0000 0000 0000 000F CF00 0000 0000 0000" + $"0000 0000 0000 0000 F000 0000 0000 0000" +}; + +data 'ICN#' (TK_APP_RESOURCES, "Tk App", purgeable) { + $"0001 0000 0002 8000 0004 7000 0008 7000" + $"0010 F000 0021 E800 0043 C400 0081 F200" + $"0107 F100 0207 F080 0407 F040 0807 E020" + $"1007 E010 200E E008 4002 E004 800E E002" + $"400E E001 200E C002 1006 E004 0806 C008" + $"0406 E010 0202 C020 0102 C040 0080 8080" + $"0041 0100 0021 0200 0011 0400 0009 0800" + $"0004 1000 0002 2000 0001 4000 0000 8000" + $"0001 0000 0003 8000 0007 F000 000F F000" + $"001F F000 003F F800 007F FC00 00FF FE00" + $"01FF FF00 03FF FF80 07FF FFC0 0FFF FFE0" + $"1FFF FFF0 3FFF FFF8 7FFF FFFC FFFF FFFE" + $"7FFF FFFF 3FFF FFFE 1FFF FFFC 0FFF FFF8" + $"07FF FFF0 03FF FFE0 01FF FFC0 00FF FF80" + $"007F FF00 003F FE00 001F FC00 000F F800" + $"0007 F000 0003 E000 0001 C000 0000 8000" +}; + +data 'ics#' (TK_APP_RESOURCES, "Tk App", purgeable) { + $"01C0 0260 04E0 09D0 1388 23C4 43C2 8281" + $"8282 4284 2188 1190 0920 0540 0280 0100" + $"01C0 03E0 07E0 0FF0 1FF8 3FFC 7FFE FFFF" + $"FFFE 7FFC 3FF8 1FF0 0FE0 07C0 0380 0100" +}; + +data 'ics4' (TK_APP_RESOURCES, "Tk App", purgeable) { + $"0000 000F C000 0000 0000 00FC 6600 0000" + $"0000 0FCC 6600 0000 0000 FCC6 66F0 0000" + $"000F CCD5 56CF 0000 00FC CC66 57CC F000" + $"0FCC CC65 56CC CF00 FCCC CC56 57CC CCF0" + $"0FCC CCC6 6CCC CCCF 00FC CCC6 5CCC CCF0" + $"000F CCC6 6CCC CF00 0000 FCCC 5CCC F000" + $"0000 0FCC CCCF 0000 0000 00FC CCF0 0000" + $"0000 000F CF00 0000 0000 0000 F000 0000" +}; + + diff --git a/macosx/tkMacOSXBitmap.c b/macosx/tkMacOSXBitmap.c new file mode 100644 index 0000000..9f930aa --- /dev/null +++ b/macosx/tkMacOSXBitmap.c @@ -0,0 +1,283 @@ +/* + * tkMacOSXBitmap.c -- + * + * This file handles the implementation of native bitmaps. + * + * Copyright (c) 1996-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * 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.2 2002/08/31 06:12:29 das Exp $ + */ + +#include "tkPort.h" +#include "tk.h" +#include "tkMacOSXInt.h" + +#include <Carbon/Carbon.h> +/* +#include <Icons.h> +#include <Dialogs.h> +#include <Resources.h> +#include <Strings.h> +*/ + +/* + * 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. */ + +/* + * 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. */ +} NativeIcon; + +/* + * This structure holds information about native bitmaps. + */ + +typedef struct { + char *name; /* Name of icon. */ + long int type; /* Type of icon. */ + int id; /* Id of icon. */ + int size; /* Size of icon. */ +} BuiltInIcon; + +/* + * This array mapps a string name to the supported builtin icons + * on the Macintosh. + */ + +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} +}; + +/* + *---------------------------------------------------------------------- + * + * TkpDefineNativeBitmaps -- + * + * 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. + * + * Side effects: + * "Name" is entered into the bitmap table and may be used from + * here on to refer to the given bitmap. + * + *---------------------------------------------------------------------- + */ + +void +TkpDefineNativeBitmaps() +{ + int new; + Tcl_HashEntry *predefHashPtr; + TkPredefBitmap *predefPtr; + CONST char * name; + 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); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpCreateNativeBitmap -- + * + * 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. + * + * Side effects: + * "Name" is entered into the bitmap table and may be used from + * here on to refer to the given bitmap. + * + *---------------------------------------------------------------------- + */ + +Pixmap +TkpCreateNativeBitmap( + Display *display, + 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); + + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + + nativeIconPtr = (NativeIcon *) source; + SetRect(&destRect, 0, 0, 32, 32); + if (nativeIconPtr->type == TYPE1) { + RGBColor white = {0xFFFF, 0xFFFF, 0xFFFF}; + + 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); + } + } + + SetGWorld(saveWorld, saveDevice); + return pix; +} + +/* + *---------------------------------------------------------------------- + * + * TkpGetNativeAppBitmap -- + * + * 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. + * + * Side effects: + * "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. */ + int *height) +{ + Pixmap pix; + CGrafPtr saveWorld; + GDHandle saveDevice; + GWorldPtr destPort; + Rect destRect; + Handle resource; + int type = -1, destWrote; + Str255 nativeName; + + /* + * 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 */ + nativeName[0] = destWrote; + + resource = GetNamedResource('cicn', nativeName); + if (resource != NULL) { + type = TYPE3; + } else { + resource = GetNamedResource('ICON', nativeName); + if (resource != NULL) { + type = TYPE2; + } + } + + if (resource == NULL) { + return NULL; + } + + pix = Tk_GetPixmap(display, None, 32, 32, 0); + destPort = TkMacOSXGetDrawablePort(pix); + + 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); + } 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); + } + + *width = 32; + *height = 32; + SetGWorld(saveWorld, saveDevice); + return pix; +} diff --git a/macosx/tkMacOSXButton.c b/macosx/tkMacOSXButton.c new file mode 100644 index 0000000..6314535 --- /dev/null +++ b/macosx/tkMacOSXButton.c @@ -0,0 +1,1580 @@ +/* + * tkMacOSXButton.c -- + * + * This file implements the Macintosh specific portion of the + * button widgets. + * + * Copyright (c) 1996-1997 by Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * 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.2 2002/08/31 06:12:29 das Exp $ + */ + +#include "tkButton.h" +#include "tkMacOSXInt.h" +#include "tkMacOSXDebug.h" + +#define DEFAULT_USE_TK_TEXT 0 + +/* + * Default insets for controls + */ +#define DEF_INSET_LEFT 2 +#define DEF_INSET_RIGHT 2 +#define DEF_INSET_TOP 2 +#define DEF_INSET_BOTTOM 4 + +#include <Carbon/Carbon.h> + +/* + * Some defines used to control what type of control is drawn. + */ + +#define DRAW_LABEL 0 /* Labels are treated genericly. */ +#define DRAW_CONTROL 1 /* Draw using the Native control. */ +#define DRAW_CUSTOM 2 /* Make our own button drawing. */ +#define DRAW_BEVEL 3 + +/* + * Declaration of Mac specific button structure. + */ + +typedef struct { + SInt16 initialValue; + SInt16 minValue; + SInt16 maxValue; + SInt16 procID; + int isBevel; +} MacControlParams; + +typedef struct { + int drawType; + Tk_3DBorder border; + int relief; + 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; + 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. + */ + CCTabHandle tabHandle; + ControlButtonContentInfo bevelButtonContent; + OpenCPicParams picParams; + Pixmap picPixmap; +} MacButton; + +/* + * Forward declarations for procedures defined later in this file: + */ + + +static OSErr SetUserPaneDrawProc(ControlRef control, + ControlUserPaneDrawProcPtr upp); +static OSErr 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)); + +extern int TkFontGetFirstTextLayout(Tk_TextLayout layout, Tk_Font * font, char * dst); +extern void TkMacOSXInitControlFontStyle(Tk_Font tkfont,ControlFontStylePtr fsPtr); + +/* + * The class procedure table for the button widgets. + */ + +Tk_ClassProcs tkpButtonProcs = { + sizeof(Tk_ClassProcs), /* size */ + TkButtonWorldChanged, /* worldChangedProc */ +}; + +static int bCount; + +int tkPictureIsOpen; + +/* + *---------------------------------------------------------------------- + * + * TkpCreateButton -- + * + * Allocate a new TkButton structure. + * + * Results: + * Returns a newly allocated TkButton structure. + * + * Side effects: + * Registers an event handler for the widget. + * + *---------------------------------------------------------------------- + */ + +TkButton * +TkpCreateButton( + Tk_Window tkwin) +{ + MacButton *macButtonPtr; + macButtonPtr = (MacButton *) ckalloc(sizeof(MacButton)); + Tk_CreateEventHandler(tkwin, ActivateMask, + 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->userPane=NULL; + macButtonPtr->control=NULL; + macButtonPtr->controlTitle[0]= + macButtonPtr->controlTitle[1]=0; + macButtonPtr->picParams.version = -2; + macButtonPtr->picParams.hRes = 0x00480000; + macButtonPtr->picParams.vRes = 0x00480000; + macButtonPtr->picParams.srcRect.top = 0; + macButtonPtr->picParams.srcRect.left = 0; + macButtonPtr->picParams.reserved1 = 0; + macButtonPtr->picParams.reserved2 = 0; + macButtonPtr->bevelButtonContent.contentType = kControlContentPictHandle; + bzero(&macButtonPtr->params, sizeof(macButtonPtr->params)); + bzero(&macButtonPtr->fontStyle,sizeof(macButtonPtr->fontStyle)); + return (TkButton *)macButtonPtr; +} + +/* + *---------------------------------------------------------------------- + * + * TkpDisplayButton -- + * + * This procedure is invoked to display a button widget. It is + * normally invoked as an idle handler. + * + * Results: + * None. + * + * Side effects: + * 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. */ +{ + MacButton *macButtonPtr = (MacButton *)clientData; + TkButton *butPtr = (TkButton *) clientData; + Tk_Window tkwin = butPtr->tkwin; + int x = 0; /* Initialization only needed to stop + * compiler warning. */ + int y; + int width, height, fullWidth, fullHeight; + int imageXOffset, imageYOffset, textXOffset, textYOffset; + int haveImage = 0, haveText = 0; + GWorldPtr destPort; + int borderWidth; + Pixmap pixmap; + int wasUsingControl; + DrawParams drawParams, * dpPtr = &drawParams; + + butPtr->flags &= ~REDRAW_PENDING; + if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { + return; + } + + pixmap = (Pixmap) Tk_WindowId(tkwin); + wasUsingControl = macButtonPtr->usingControl; + + if (TkMacOSXComputeDrawParams(butPtr, &drawParams) ) { + macButtonPtr->usingControl=1; + macButtonPtr->useTkText=DEFAULT_USE_TK_TEXT; + } else { + macButtonPtr->usingControl=0; + macButtonPtr->useTkText=1; + } + + /* + * set up clipping region + */ + + TkMacOSXSetUpClippingRgn(pixmap); + + /* + * 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); + } + } + + /* + * 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 (macButtonPtr->usingControl) { + borderWidth = 0; + /* + * This part uses Macintosh rather than Tk calls to draw + * to the screen. Make sure the ports etc. are set correctly. + */ + + destPort = TkMacOSXGetDrawablePort(pixmap); + SetGWorld(destPort, NULL); + 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; + } + + /* + * 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; + } + haveText = (butPtr->textWidth != 0 && butPtr->textHeight != 0); + if (butPtr->compound != COMPOUND_NONE && haveImage && haveText) { + imageXOffset = 0; + imageYOffset = 0; + 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; + } + + if (butPtr->image != NULL) { + if ((butPtr->selectImage != NULL) && + (butPtr->flags & SELECTED)) { + Tk_RedrawImage(butPtr->selectImage, 0, 0, + width, height, pixmap, x + imageXOffset, + y + imageYOffset); + } else { + Tk_RedrawImage(butPtr->image, 0, 0, width, + height, pixmap, x + imageXOffset, + y + imageYOffset); + } + } else { + XSetClipOrigin(butPtr->display, dpPtr->gc, x + imageXOffset, + y + imageYOffset); + XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, dpPtr->gc, + 0, 0, (unsigned int) width, + (unsigned int) height, x + imageXOffset, + y + 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) { + 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; + } + if (butPtr->image != NULL) { + if ((butPtr->selectImage != NULL) && + (butPtr->flags & SELECTED)) { + Tk_RedrawImage(butPtr->selectImage, 0, 0, width, + height, pixmap, x, y); + } else { + Tk_RedrawImage(butPtr->image, 0, 0, width, height, + pixmap, x, y); + } + } 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 { + TkComputeAnchor(butPtr->anchor, tkwin, butPtr->padX, + butPtr->padY, + butPtr->indicatorSpace + butPtr->textWidth, + butPtr->textHeight, &x, &y); + + x += butPtr->indicatorSpace; + + if (macButtonPtr->useTkText) { + Tk_DrawTextLayout(butPtr->display, pixmap, dpPtr->gc, + butPtr->textLayout, x, y, 0, -1); + } + y += butPtr->textHeight/2; + } + } + } + + /* + * If the button is disabled with a stipple rather than a special + * 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. + */ + + if (macButtonPtr->useTkText) { + if ((butPtr->state == STATE_DISABLED) + && ((butPtr->disabledFg == NULL) || (butPtr->image != NULL))) { + if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn + && (butPtr->selectBorder != NULL)) { + XSetForeground(butPtr->display, butPtr->disabledGC, + Tk_3DBorderColor(butPtr->selectBorder)->pixel); + } + XFillRectangle(butPtr->display, pixmap, butPtr->disabledGC, + butPtr->inset, butPtr->inset, + (unsigned) (Tk_Width(tkwin) - 2*butPtr->inset), + (unsigned) (Tk_Height(tkwin) - 2*butPtr->inset)); + if ((butPtr->flags & SELECTED) && !butPtr->indicatorOn + && (butPtr->selectBorder != NULL)) { + XSetForeground(butPtr->display, butPtr->disabledGC, + 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); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * Results: + * None. + * + * Side effects: + * The button's window may change size. + * + *---------------------------------------------------------------------- + */ + +void +TkpComputeButtonGeometry( + TkButton *butPtr) /* Button whose geometry may have changed. */ +{ + int width, height, avgWidth, haveImage = 0, haveText = 0; + int xInset, yInset; + int 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; + } else if (butPtr->bitmap != None) { + 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); + } + + /* + * If the button is compound (ie, it shows both an image and text), + * the new geometry is a combination of the image and text geometry. + * We only honor the compound bit if the button has both text and an + * image, because otherwise it is not really a compound button. + */ + + 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; + + } 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; + } + } + } + + /* + * Now figure out the size of the border decorations for the button. + */ + + if (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, + * 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, + * 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 + * 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 + * highlight width as there is also one pixel of spacing. + * 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; + } + + 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; + } + } + } 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; + } else { + xInset = butPtr->indicatorSpace+butPtr->inset*2; + yInset = butPtr->inset*2; + } + Tk_GeometryRequest(butPtr->tkwin, width + xInset, height + yInset); + Tk_SetInternalBorder(butPtr->tkwin, butPtr->inset); +} + +/* + *---------------------------------------------------------------------- + * + * TkpDestroyButton -- + * + * Free data structures associated with the button control. + * + * Results: + * None. + * + * Side effects: + * Restores the default control state. + * + *---------------------------------------------------------------------- + */ + +void +TkpDestroyButton( + TkButton *butPtr) +{ + MacButton *mbPtr = ( MacButton *) butPtr; /* Mac button. */ + if (mbPtr->userPane) { + DisposeControl(mbPtr->userPane); + mbPtr->userPane = NULL; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXInitControl -- + * + * This procedure initialises a Carbon control + * + * Results: + * 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 + * + *---------------------------------------------------------------------- + */ + +int +TkMacOSXInitControl ( + MacButton *mbPtr, /* Mac button. */ + GWorldPtr destPort, + GC gc, + Pixmap pixmap, + Rect *paneRect, + Rect *cntrRect +) +{ + OSErr status; + TkButton * butPtr = ( TkButton * )mbPtr; + ControlRef rootControl; + SInt16 procID; + Boolean initiallyVisible; + SInt16 initialValue; + SInt16 minValue; + SInt16 maxValue; + SInt32 controlReference; + + rootControl = TkMacOSXGetRootControl(Tk_WindowId(butPtr->tkwin)); + mbPtr->windowRef + = GetWindowFromPort(TkMacOSXGetDrawablePort(Tk_WindowId(butPtr->tkwin))); + + /* + * Set up the user pane + */ + + initiallyVisible=false; + 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 ); + + if (!mbPtr->userPane) { + fprintf(stderr,"Failed to create user pane control\n"); + return 1; + } + + if ((status=EmbedControl(mbPtr->userPane,rootControl))!=noErr) { + fprintf(stderr,"Failed to embed user pane control %d\n", status); + return 1; + } + + SetUserPaneSetUpSpecialBackgroundProc(mbPtr->userPane, + 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 ); + + if (!mbPtr->control) { + fprintf(stderr,"failed to create control of type %d\n",procID); + return 1; + } + + if (EmbedControl(mbPtr->control,mbPtr->userPane) != noErr ) { + fprintf(stderr,"failed to embed control of type %d\n",procID); + 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. + * + * Results: + * None. + * + * Side effects: + * 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 */ + +{ + TkButton * butPtr = ( TkButton *)mbPtr; + int err; + TkWindow * winPtr; + Rect paneRect; + Rect cntrRect; + int hilitePart = -1; + + + 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.bottom-=butPtr->inset; +*/ + 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 + */ + + 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; + } + } + if (!(mbPtr->flags & 1)) { + 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; + + len = TkFontGetFirstTextLayout(butPtr->textLayout, + &font, controlTitle); + controlTitle[len] = 0; + if (bcmp(mbPtr->controlTitle, controlTitle, len+1)) { + CFStringRef cf; + cf = CFStringCreateWithCString(NULL, + 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) { + fprintf(stderr,"SetControlFontStyle failed\n"); + } + bcopy(&fontStyle, &mbPtr->fontStyle, + sizeof(fontStyle)); + } + } + } + if (mbPtr->params.isBevel) { + /* Initialiase the image/button parameters */ + SetupBevelButton(mbPtr, mbPtr->control, destPort, + gc, pixmap); + } + + if (butPtr->flags & SELECTED) { + SetControlValue(mbPtr->control, 1); + } else { + SetControlValue(mbPtr->control, 0); + } + + if (!Tk_MacOSXIsAppInFront() || butPtr->state == STATE_DISABLED) { + HiliteControl(mbPtr->control, kControlInactivePart); + } else if (butPtr->state == STATE_ACTIVE) { + if (mbPtr->params.isBevel) { + HiliteControl(mbPtr->control, kControlButtonPart); + } else { + switch (butPtr->type) { + case TYPE_BUTTON: + HiliteControl(mbPtr->control, kControlButtonPart); + break; + case TYPE_RADIO_BUTTON: + HiliteControl(mbPtr->control, kControlRadioButtonPart); + break; + case TYPE_CHECK_BUTTON: + HiliteControl(mbPtr->control, kControlCheckBoxPart); + break; + } + } + } else { + HiliteControl(mbPtr->control, kControlNoPart); + } + 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 ) { + } + } + + if (mbPtr->flags&2) { + ShowControl(mbPtr->control); + ShowControl(mbPtr->userPane); + mbPtr->flags ^= 2; + } else { + Draw1Control(mbPtr->userPane); + SetControlVisibility(mbPtr->control, true, true); + } + + if (mbPtr->params.isBevel) { + KillPicture(mbPtr->bevelButtonContent.u.picture); + } +} + +/* + *-------------------------------------------------------------- + * + * SetupBevelButton -- + * + * Sets up the Bevel Button with image by copying the + * source image onto the PicHandle for the button. + * + * Results: + * None + * + * Side effects: + * 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 */ + ) +{ + int err; + TkButton *butPtr = ( TkButton *)mbPtr; + int height, width; + ControlButtonGraphicAlignment theAlignment; + + SetPort(destPort); + + if (butPtr->image != None) { + Tk_SizeOfImage(butPtr->image, + &width, &height); + } else { + Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, + &width, &height); + } + + if ((butPtr->width > 0) && (butPtr->width < width)) { + width = butPtr->width; + } + if ((butPtr->height > 0) && (butPtr->height < 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 + */ + + if (!(mbPtr->bevelButtonContent.u.picture + = OpenCPicture(&mbPtr->picParams)) ) { + fprintf(stderr,"OpenCPicture failed\n"); + } + tkPictureIsOpen = 1; + + /* + * TO DO - There is one case where XCopyPlane calls CopyDeepMask, + * 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->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); + } + + ClosePicture(); + tkPictureIsOpen = 0; + + if ( (err=SetControlData(controlHandle, kControlButtonPart, + kControlBevelButtonContentTag, + sizeof(ControlButtonContentInfo), + (char *) &mbPtr->bevelButtonContent)) != noErr ) { + fprintf(stderr, + "SetControlData BevelButtonContent failed, %d\n", err ); + } + + 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; + } else if (butPtr->anchor == TK_ANCHOR_SE) { + theAlignment = kControlBevelButtonAlignBottomRight; + } else if (butPtr->anchor == TK_ANCHOR_S) { + theAlignment = kControlBevelButtonAlignBottom; + } else if (butPtr->anchor == TK_ANCHOR_SW) { + theAlignment = kControlBevelButtonAlignBottomLeft; + } else if (butPtr->anchor == TK_ANCHOR_W) { + theAlignment = kControlBevelButtonAlignLeft; + } else if (butPtr->anchor == TK_ANCHOR_NW) { + theAlignment = kControlBevelButtonAlignTopLeft; + } else if (butPtr->anchor == TK_ANCHOR_CENTER) { + theAlignment = kControlBevelButtonAlignCenter; + } + + if ((err=SetControlData(controlHandle, kControlButtonPart, + kControlBevelButtonGraphicAlignTag, + sizeof(ControlButtonGraphicAlignment), + (char *) &theAlignment)) != noErr ) { + fprintf(stderr, + "SetControlData BevelButtonGraphicAlign failed, %d\n", err ); + } + +} + +/* + *-------------------------------------------------------------- + * + * SetUserPaneDrawProc -- + * + * Utility function to add a UserPaneDrawProc + * to a userPane control. From MoreControls code + * from Apple DTS. + * + * Results: + * MacOS system error. + * + * Side effects: + * The user pane gets a new UserPaneDrawProc. + * + *-------------------------------------------------------------- + */ +OSErr SetUserPaneDrawProc ( + ControlRef control, + ControlUserPaneDrawProcPtr upp) +{ + ControlUserPaneDrawUPP myControlUserPaneDrawUPP; + myControlUserPaneDrawUPP = NewControlUserPaneDrawUPP(upp); + return SetControlData (control, + kControlNoPart, kControlUserPaneDrawProcTag, + sizeof(myControlUserPaneDrawUPP), + (Ptr) &myControlUserPaneDrawUPP); +} + +/* + *-------------------------------------------------------------- + * + * SetUserPaneSetUpSpecialBackgroundProc -- + * + * Utility function to add a UserPaneBackgroundProc + * to a userPane control + * + * Results: + * MacOS system error. + * + * Side effects: + * The user pane gets a new UserPaneBackgroundProc. + * + *-------------------------------------------------------------- + */ +OSErr +SetUserPaneSetUpSpecialBackgroundProc( + ControlRef control, + ControlUserPaneBackgroundProcPtr upp) +{ + ControlUserPaneBackgroundUPP myControlUserPaneBackgroundUPP; + myControlUserPaneBackgroundUPP = NewControlUserPaneBackgroundUPP(upp); + return SetControlData (control, kControlNoPart, + kControlUserPaneBackgroundProcTag, + sizeof(myControlUserPaneBackgroundUPP), + (Ptr) &myControlUserPaneBackgroundUPP); +} + +/* + *-------------------------------------------------------------- + * + * UserPaneDraw -- + * + * This function draws the background of the user pane that will + * lie under checkboxes and radiobuttons. + * + * Results: + * None. + * + * Side effects: + * The user pane gets updated to the current color. + * + *-------------------------------------------------------------- + */ +void +UserPaneDraw( + ControlRef control, + ControlPartCode cpc) +{ + Rect contrlRect; + MacButton * mbPtr; + mbPtr = ( MacButton *)GetControlReference(control); + GetControlBounds(control,&contrlRect); + RGBBackColor (&mbPtr->userPaneBackground); + EraseRect (&contrlRect); +} + +/* + *-------------------------------------------------------------- + * + * UserPaneBackgroundProc -- + * + * This function sets up the background of the user pane that will + * lie under checkboxes and radiobuttons. + * + * Results: + * None. + * + * Side effects: + * The user pane background gets set to the current color. + * + *-------------------------------------------------------------- + */ + +void +UserPaneBackgroundProc( + ControlHandle control, + ControlBackgroundPtr info) +{ + MacButton * mbPtr; + mbPtr = ( MacButton *)GetControlReference(control); + if (info->colorDevice) { + RGBBackColor (&mbPtr->userPaneBackground); + } +} + +/* + *-------------------------------------------------------------- + * + * 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. + * + * Under Appearance, we just set the pointer that will be + * used by the UserPaneDrawProc. + * + * Results: + * None. + * + * Side effects: + * The Macintosh control may get a custom palette installed. + * + *-------------------------------------------------------------- + */ + +static int +UpdateControlColors(MacButton * mbPtr) +{ + XColor *xcolor; + 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. + * 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); + } else { + xcolor = Tk_3DBorderColor(butPtr->normalBorder); + } + TkSetMacColor(xcolor->pixel, &mbPtr->userPaneBackground); + + return false; +} +/* + *-------------------------------------------------------------- + * + * ButtonEventProc -- + * + * This procedure is invoked by the Tk dispatcher for various + * events on buttons. + * + * Results: + * None. + * + * Side effects: + * When it gets exposed, it is redisplayed. + * + *-------------------------------------------------------------- + */ + +static void +ButtonEventProc( + 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; + } + } +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXComputeControlParams -- + * + * This procedure computes the various parameters used + * when creating a Carbon control (NewControl) + * These are determined by the various tk button parameters + * + * Results: + * None. + * + * Side effects: + * Sets the control initialisation parameters + * + *---------------------------------------------------------------------- + */ + +static void +TkMacOSXComputeControlParams(TkButton * butPtr, MacControlParams * paramsPtr ) +{ + paramsPtr->isBevel = 0; + + /* + * 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 = 1; + paramsPtr->procID = kControlRadioButtonProc; + } else { + paramsPtr->initialValue = 0; + paramsPtr->minValue = kControlBehaviorOffsetContents| + kControlBehaviorSticky| + 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_CHECK_BUTTON: + if (((butPtr->image == None) + && (butPtr->bitmap == None)) + || (butPtr->indicatorOn)) { + paramsPtr->initialValue = 1; + paramsPtr->minValue = 0; + paramsPtr->maxValue = 1; + paramsPtr->procID = kControlCheckBoxProc; + } else { + paramsPtr->initialValue = 0; + paramsPtr->minValue = kControlBehaviorOffsetContents + | kControlBehaviorSticky + | 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; + } +} +/* + *---------------------------------------------------------------------- + * + * TkMacOSXComputeDrawParams -- + * + * 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. + * + * Side effects: + * Sets the button draw parameters + * + *---------------------------------------------------------------------- + */ + +static int +TkMacOSXComputeDrawParams(TkButton * butPtr, DrawParams * dpPtr) +{ + 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; + } else { + dpPtr->gc = butPtr->normalTextGC; + } + + 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. + * However, don't do this in the presence of Appearance, since + * then the bevel button will take care of the relief. + */ + + 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; + } + } + + /* + * Determine the draw type + */ + if (butPtr->type == TYPE_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; + } + } + } + } 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; + } + } + + if ((dpPtr->drawType == DRAW_CONTROL) || (dpPtr->drawType == DRAW_BEVEL)) { + return 1; + } else { + return 0; + } +} diff --git a/macosx/tkMacOSXClipboard.c b/macosx/tkMacOSXClipboard.c new file mode 100644 index 0000000..7bfa7ce --- /dev/null +++ b/macosx/tkMacOSXClipboard.c @@ -0,0 +1,321 @@ +/* + * tkMacOSXClipboard.c -- + * + * This file manages the clipboard for the Tk toolkit. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * 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.2 2002/08/31 06:12:29 das Exp $ + */ + +#include "tkInt.h" +#include "tkPort.h" +#include "tkMacOSXInt.h" +#include "tkSelect.h" + +#include <Carbon/Carbon.h> + + +/* + *---------------------------------------------------------------------- + * + * TkSelGetSelection -- + * + * 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. + * + * Side effects: + * 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. */ +{ + int result; + int err; + long length; + ScrapRef scrapRef; + 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; + } + + 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; + + 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_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); + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * + * TkSetSelectionOwner -- + * + * This function claims ownership of the specified selection. + * If the selection is CLIPBOARD, then we empty the system + * clipboard. + * + * Results: + * None. + * + * Side effects: + * 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? */ +{ + Tk_Window tkwin; + TkDisplay *dispPtr; + + /* + * This is a gross hack because the Tk_InternAtom interface is broken. + * It expects a Tk_Window, even though it only needs a Tk_Display. + */ + + 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. + */ + + dispPtr = TkGetMainInfoList()->winPtr->dispPtr; + if (dispPtr->clipboardActive) { + return; + } + ClearCurrentScrap(); + } +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkSelUpdateClipboard( + TkWindow *winPtr, /* Window associated with clipboard. */ + TkClipboardTarget *targetPtr) /* Info about the content. */ +{ +} + +/* + *-------------------------------------------------------------- + * + * TkSelEventProc -- + * + * This procedure is invoked whenever a selection-related + * event occurs. + * + * Results: + * None. + * + * Side effects: + * 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. */ +{ + if (eventPtr->type == SelectionClear) { + TkSelClearSelection(tkwin, eventPtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkSelPropProc -- + * + * 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. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkSelPropProc( + register XEvent *eventPtr) /* X PropertyChange event. */ +{ +} + +/* + *---------------------------------------------------------------------- + * + * TkSuspendClipboard -- + * + * Handle clipboard conversion as required by the suppend event. + * This function is also called on exit. + * + * Results: + * None. + * + * Side effects: + * The local scrap is moved to the global scrap. + * + *---------------------------------------------------------------------- + */ + +void +TkSuspendClipboard() +{ + TkClipboardTarget *targetPtr; + TkClipboardBuffer *cbPtr; + TkDisplay *dispPtr; + char *buffer, *p, *endPtr, *buffPtr; + long length; + ScrapRef scrapRef; + + dispPtr = TkGetDisplayList(); + if ((dispPtr == NULL) || !dispPtr->clipboardActive) { + return; + } + + for (targetPtr = dispPtr->clipTargetPtr; targetPtr != NULL; + targetPtr = targetPtr->nextPtr) { + if (targetPtr->type == XA_STRING) + break; + } + if (targetPtr != NULL) { + Tcl_DString encodedText; + + 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); + ckfree(buffer); + } + + /* + * 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.) + */ + + if (TkGetMainInfoList() != NULL) { + Tk_ClearSelection((Tk_Window) TkGetMainInfoList()->winPtr, + Tk_InternAtom((Tk_Window) TkGetMainInfoList()->winPtr, + "CLIPBOARD")); + } + + return; +} diff --git a/macosx/tkMacOSXColor.c b/macosx/tkMacOSXColor.c new file mode 100644 index 0000000..492f098 --- /dev/null +++ b/macosx/tkMacOSXColor.c @@ -0,0 +1,448 @@ +/* + * 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. + * + * Copyright (c) 1990-1994 The Regents of the University of California. + * Copyright (c) 1994-1996 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * 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.2 2002/08/31 06:12:29 das Exp $ + */ + +#include <tkColor.h> +#include "tkMacOSXInt.h" +#include <Carbon/Carbon.h> + +/* + * 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. + */ +/* + * Stubbed out for OS X +static AuxCtlHandle defaultAuxCtlHandle = NULL; +*/ + +/* + * Forward declarations for procedures defined later in this file: + */ + +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)); + +/* + *---------------------------------------------------------------------- + * + * TkSetMacColor -- + * + * Populates a Macintosh RGBColor structure from a X style + * pixel value. + * + * Results: + * Returns false if not a real pixel, true otherwise. + * + * Side effects: + * The variable macColor is updated to the pixels value. + * + *---------------------------------------------------------------------- + */ + +int +TkSetMacColor( + unsigned long pixel, /* Pixel value to convert. */ + RGBColor *macColor) /* Mac color struct to modify. */ +{ + switch (pixel >> 24) { + case HIGHLIGHT_PIXEL: + LMGetHiliteRGB(macColor); + return true; + case HIGHLIGHT_TEXT_PIXEL: + 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; + } +} + +/* + *---------------------------------------------------------------------- + * + * Stub functions -- + * + * These functions are just stubs for functions that either + * don't make sense on the Mac or have yet to be implemented. + * + * Results: + * None. + * + * Side effects: + * These calls do nothing - which may not be expected. + * + *---------------------------------------------------------------------- + */ + +Status +XAllocColor( + Display *display, /* Display. */ + Colormap map, /* Not used. */ + XColor *colorPtr) /* XColor struct to modify. */ +{ + display->request++; + colorPtr->pixel = TkpGetPixel(colorPtr); + return 1; +} + +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++; +} + +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. */ +{ + /* + * 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. + */ +} + +/* + *---------------------------------------------------------------------- + * + * TkpGetColor -- + * + * Allocate a new TkColor for the color with the given name. + * + * Results: + * 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. + * + *---------------------------------------------------------------------- + */ + +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). */ +{ + Display *display = Tk_Display(tkwin); + Colormap colormap = Tk_Colormap(tkwin); + TkColor *tkColPtr; + XColor color; + + /* + * Check to see if this is a system color. Otherwise, XParseColor + * will do all the work. + */ + if (strncasecmp(name, "system", 6) == 0) { + int foundSystemColor = false; + RGBColor rgbValue; + char pixelCode = 0; + + if (!strcasecmp(name+6, "Highlight")) { + LMGetHiliteRGB(&rgbValue); + pixelCode = HIGHLIGHT_PIXEL; + foundSystemColor = true; + } else if (!strcasecmp(name+6, "HighlightText")) { + LMGetHiliteRGB(&rgbValue); + 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; + } + + tkColPtr = (TkColor *) ckalloc(sizeof(TkColor)); + tkColPtr->color = color; + + return tkColPtr; +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * 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. + * + * Side effects: + * 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. */ +{ + TkColor *tkColPtr = (TkColor *) ckalloc(sizeof(TkColor)); + + tkColPtr->color.red = colorPtr->red; + tkColPtr->color.green = colorPtr->green; + tkColPtr->color.blue = colorPtr->blue; + tkColPtr->color.pixel = TkpGetPixel(&tkColPtr->color); + return tkColPtr; +} + +/* + *---------------------------------------------------------------------- + * + * GetControlPartColor -- + * + * 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 'cctb' 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 +GetControlPartColor( + short part, /* Part code. */ + RGBColor *macColor) /* Pointer to Mac color. */ +{ +/* Stubbed out for OS X + short index; + CCTabHandle ccTab; + + if (defaultAuxCtlHandle == NULL) { + GetAuxiliaryControlRecord(NULL, &defaultAuxCtlHandle); + } + ccTab = (**defaultAuxCtlHandle).acCTable; + if(ccTab && (ResError() == noErr)) { + for(index = 0; index <= (**ccTab).ctSize; index++) { + if((**ccTab).ctTable[index].value == part) { + *macColor = (**ccTab).ctTable[index].rgb; + return true; + } + } + } +*/ + return false; +} + +/* + *---------------------------------------------------------------------- + * + * GetWindowPartColor -- + * + * 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. + * + * 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 +GetWindowPartColor( + short part, /* Part code. */ + RGBColor *macColor) /* Pointer to Mac color. */ +{ + short index; + WCTabHandle wcTab; + + 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; + } +} + +/* + *---------------------------------------------------------------------- + * + * 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 */ +{ + + /* 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; +} diff --git a/macosx/tkMacOSXConfig.c b/macosx/tkMacOSXConfig.c new file mode 100644 index 0000000..a89d51f --- /dev/null +++ b/macosx/tkMacOSXConfig.c @@ -0,0 +1,46 @@ +/* + * tkMacOSXConfig.c -- + * + * This module implements the Macintosh system defaults for + * the configuration package. + * + * Copyright (c) 1997 by Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * 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.2 2002/08/31 06:12:29 das Exp $ + */ + +#include "tk.h" +#include "tkInt.h" + + +/* + *---------------------------------------------------------------------- + * + * TkpGetSystemDefault -- + * + * 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. + * + * Side effects: + * 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. */ +{ + return NULL; +} diff --git a/macosx/tkMacOSXCursor.c b/macosx/tkMacOSXCursor.c new file mode 100644 index 0000000..a1bbbb4 --- /dev/null +++ b/macosx/tkMacOSXCursor.c @@ -0,0 +1,406 @@ +/* + * tkMacOSXCursor.c -- + * + * This file contains Macintosh specific cursor related routines. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * 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.2 2002/08/31 06:12:29 das Exp $ + */ + +#include "tkPort.h" +#include "tkInt.h" +#include "tkMacOSXInt.h" + +#include <Carbon/Carbon.h> + +/* + * There are three different ways to set the cursor on the Mac. + */ +#define ARROW 0 /* The arrow cursor. */ +#define COLOR 1 /* Cursors of type crsr. */ +#define NORMAL 2 /* Cursors of type CURS. */ + +/* + * The following data structure contains the system specific data + * necessary to control Windows cursors. + */ + +typedef struct { + TkCursor info; /* Generic cursor info used by tkCursor.c */ + Handle macCursor; /* Resource containing Macintosh cursor. */ + int type; /* Type of Mac cursor: arrow, crsr, CURS */ +} TkMacOSXCursor; + +/* + * The table below is used to map from the name of a predefined cursor + * to its resource identifier. + */ + +static struct CursorName { + char *name; + int id; +} cursorNames[] = { + {"ibeam", 1}, + {"text", 1}, + {"xterm", 1}, + {"cross", 2}, + {"crosshair", 2}, + {"cross-hair", 2}, + {"plus", 3}, + {"watch", 4}, + {"arrow", 5}, + {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 */ + +/* + * Declarations of procedures local to this file + */ + +static void FindCursorByName _ANSI_ARGS_ ((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. + * + * Results: + * Fills the macCursorPtr record. + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +void +FindCursorByName( + TkMacOSXCursor *macCursorPtr, + CONST char *string) +{ + Handle resource; + Str255 curName; + int destWrote, inCurLen; + + inCurLen = strlen(string); + if (inCurLen > 255) { + 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 */ + curName[0] = destWrote; + + 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; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkGetCursorByName -- + * + * Retrieve a system cursor by name. + * + * Results: + * Returns a new cursor, or NULL on errors. + * + * Side effects: + * 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. */ +{ + struct CursorName *namePtr; + TkMacOSXCursor *macCursorPtr; + + macCursorPtr = (TkMacOSXCursor *) ckalloc(sizeof(TkMacOSXCursor)); + macCursorPtr->info.cursor = (Tk_Cursor) macCursorPtr; + + /* + * To find a cursor we must first determine if it is one of the + * builtin cursors or the standard arrow cursor. Otherwise, we + * attempt to load the cursor as a named Mac resource. + */ + + for (namePtr = cursorNames; namePtr->name != NULL; namePtr++) { + if (strcmp(namePtr->name, string) == 0) { + break; + } + } + + + if (namePtr->name != NULL) { + if (namePtr->id == 5) { + macCursorPtr->macCursor = (Handle) -1; + macCursorPtr->type = ARROW; + } else { + macCursorPtr->macCursor = (Handle) GetCursor(namePtr->id); + macCursorPtr->type = NORMAL; + } + } else { + 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 (macCursorPtr->macCursor == NULL) { + ckfree((char *)macCursorPtr); + Tcl_AppendResult(interp, "bad cursor spec \"", string, "\"", + (char *) NULL); + return NULL; + } else { + return (TkCursor *) macCursorPtr; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkCreateCursorFromData -- + * + * Creates a cursor from the source and mask bits. + * + * Results: + * Returns a new cursor, or NULL on errors. + * + * Side effects: + * 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. */ +{ + return NULL; +} + +/* + *---------------------------------------------------------------------- + * + * TkpFreeCursor -- + * + * This procedure is called to release a cursor allocated by + * TkGetCursorByName. + * + * Results: + * None. + * + * Side effects: + * The cursor data structure is deallocated. + * + *---------------------------------------------------------------------- + */ + +void +TkpFreeCursor( + TkCursor *cursorPtr) +{ + TkMacOSXCursor *macCursorPtr = (TkMacOSXCursor *) cursorPtr; + + switch (macCursorPtr->type) { + case COLOR: + DisposeCCursor((CCrsrHandle) macCursorPtr->macCursor); + break; + case NORMAL: + ReleaseResource(macCursorPtr->macCursor); + break; + } + + if (macCursorPtr == gCurrentCursor) { + gCurrentCursor = NULL; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXInstallCursor -- + * + * Installs either the current cursor as defined by TkpSetCursor + * or a resize cursor as the cursor the Macintosh should currently + * display. + * + * Results: + * None. + * + * Side effects: + * Changes the Macintosh mouse cursor. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXInstallCursor( + int resizeOverride) +{ + TkMacOSXCursor *macCursorPtr = gCurrentCursor; + CCrsrHandle ccursor; + CursHandle cursor; + + gResizeOverride = resizeOverride; + + if (resizeOverride) { + cursor = (CursHandle) GetNamedResource('CURS', "\presize"); + if (cursor) { + SetCursor(*cursor); + } else { + /* + fprintf(stderr,"Resize cursor failed, %d\n", ResError()); + */ + } + } else if (macCursorPtr == NULL || macCursorPtr->type == ARROW) { + SetThemeCursor(kThemeArrowCursor); + } else { + switch (macCursorPtr->type) { + case COLOR: + ccursor = (CCrsrHandle) macCursorPtr->macCursor; + SetCCursor(ccursor); + break; + case NORMAL: + cursor = (CursHandle) macCursorPtr->macCursor; + SetCursor(*cursor); + break; + } + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpSetCursor -- + * + * Set the current cursor and install it. + * + * Results: + * None. + * + * Side effects: + * Changes the current cursor. + * + *---------------------------------------------------------------------- + */ + +void +TkpSetCursor( + TkpCursor cursor) +{ + if (!gTkOwnsCursor) { + return; + } + if (cursor == None) { + gCurrentCursor = NULL; + } else { + gCurrentCursor = (TkMacOSXCursor *) cursor; + } + + if (Tk_MacOSXIsAppInFront()) { + TkMacOSXInstallCursor(gResizeOverride); + } +} + +/* + *---------------------------------------------------------------------- + * + * Tk_MacOSXTkOwnsCursor -- + * + * Sets whether Tk has the right to adjust the cursor. + * + * Results: + * None. + * + * Side effects: + * May keep Tk from changing the cursor. + * + *---------------------------------------------------------------------- + */ + +void +Tk_MacOSXTkOwnsCursor( + int tkOwnsIt) +{ + gTkOwnsCursor = tkOwnsIt; +} diff --git a/macosx/tkMacOSXCursors.r b/macosx/tkMacOSXCursors.r new file mode 100644 index 0000000..51abc74 --- /dev/null +++ b/macosx/tkMacOSXCursors.r @@ -0,0 +1,130 @@ +/* + * tkMacOSXCursors.r -- + * + * This file defines a set of Macintosh cursor resources that + * 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 $ + */ + +/* + * These are resource definitions for Macintosh cursors. + * The are identified and loaded by the "name" of the + * cursor. However, the ids must be unique. + */ + +data 'CURS' (1000, "hand") { + $"0180 1A70 2648 264A 124D 1249 6809 9801" + $"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" +}; + +data 'CURS' (1002, "bucket") { + $"0000 0000 0600 0980 0940 0B30 0D18 090C" + $"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" +}; + +data 'CURS' (1003, "cancel") { + $"0000 0000 0000 0000 3180 4A40 4A40 3F80" + $"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" +}; + +data 'CURS' (1004, "resize") { + $"FFFF 8001 BF01 A181 A1F9 A18D A18D BF8D" + $"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" +}; + +data 'CURS' (1005, "eyedrop") { + $"000E 001F 001F 00FF 007E 00B8 0118 0228" + $"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" +}; + +data 'CURS' (1006, "eyedrop-full") { + $"000E 001F 001F 00FF 007E 00B8 0118 0328" + $"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" +}; + +data 'CURS' (1007, "zoom-in") { + $"0780 1860 2790 5868 5028 A014 AFD4 AFD4" + $"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" +}; + +data 'CURS' (1008, "zoom-out") { + $"0780 1860 2790 5868 5328 A314 AFD4 AFD4" + $"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" +}; + +/* + * 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 + * same name preference will be given to the color + * cursors. + */ + +data 'crsr' (1000, "hand") { + $"8001 0000 0060 0000 0092 0000 0000 0000" + $"0000 0000 0180 1A70 2648 264A 124D 1249" + $"6809 9801 8802 4002 2002 2004 1004 0808" + $"0408 0408 0180 1BF0 3FF8 3FFA 1FFF 1FFF" + $"6FFF FFFF FFFE 7FFE 3FFE 3FFC 1FFC 0FF8" + $"07F8 07F8 0008 0008 0000 0000 0000 0000" + $"0000 0000 8004 0000 0000 0010 0010 0000" + $"0000 0000 0000 0048 0000 0048 0000 0000" + $"0002 0001 0002 0000 0000 0000 00D2 0000" + $"0000 0003 C000 03CD 7F00 0D7D 75C0 0D7D" + $"75CC 035D 75F7 035D 75D7 3CD5 55D7 D7D5" + $"5557 D5D5 555C 3555 555C 0D55 555C 0D55" + $"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" +}; + +data 'crsr' (1001, "fist") { + $"8001 0000 0060 0000 0092 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0DB0 124C" + $"100A 0802 1802 2002 2002 2004 1004 0808" + $"0408 0408 0000 0000 0000 0000 0DB0 1FFC" + $"1FFE 0FFE 1FFE 3FFE 3FFE 3FFC 1FFC 0FF8" + $"07F8 07F8 0008 0008 0000 0000 0000 0000" + $"0000 0000 8004 0000 0000 0010 0010 0000" + $"0000 0000 0000 0048 0000 0048 0000 0000" + $"0002 0001 0002 0000 0000 0000 00D2 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0000 00F3 CF00 035D 75F0 0355 55DC 00D5" + $"555C 03D5 555C 0D55 555C 0D55 555C 0D55" + $"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" +}; + diff --git a/macosx/tkMacOSXDebug.c b/macosx/tkMacOSXDebug.c new file mode 100644 index 0000000..53997e8 --- /dev/null +++ b/macosx/tkMacOSXDebug.c @@ -0,0 +1,439 @@ +/* + * tkMacOSXDebug.c -- + * + * Implementation of Macintosh specific functions for debugging MacOS events, + * regions, etc... + * + * Copyright 2001, Apple Computer, Inc. + * + * 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. + */ + +#include "tkMacOSXDebug.h" + +typedef struct { + EventKind kind; + char * name; +} MyEventName; + +typedef struct { + EventClass c; + MyEventName * names; +} MyEventNameList; + +static MyEventName windowEventNames [] = { + { kEventWindowUpdate,"Update"}, + { kEventWindowDrawContent,"DrawContent"}, + { kEventWindowActivated,"Activated"}, + { kEventWindowDeactivated,"Deactivated"}, + { kEventWindowGetClickActivation,"GetClickActivation"}, + { kEventWindowShowing,"Showing"}, + { kEventWindowHiding,"Hiding"}, + { kEventWindowShown,"Shown"}, + { kEventWindowHidden,"Hidden"}, + { kEventWindowBoundsChanging,"BoundsChanging"}, + { kEventWindowBoundsChanged,"BoundsChanged"}, + { kEventWindowResizeStarted,"ResizeStarted"}, + { kEventWindowResizeCompleted,"ResizeCompleted"}, + { kEventWindowDragStarted,"DragStarted"}, + { kEventWindowDragCompleted,"DragCompleted"}, + { kEventWindowClickDragRgn,"ClickDragRgn"}, + { kEventWindowClickResizeRgn,"ClickResizeRgn"}, + { kEventWindowClickCollapseRgn,"ClickCollapseRgn"}, + { kEventWindowClickCloseRgn,"ClickCloseRgn"}, + { kEventWindowClickZoomRgn,"ClickZoomRgn"}, + { kEventWindowClickContentRgn,"ClickContentRgn"}, + { kEventWindowClickProxyIconRgn,"ClickProxyIconRgn"}, + { kEventWindowCursorChange,"CursorChange" }, + { kEventWindowCollapse,"Collapse"}, + { kEventWindowCollapsed,"Collapsed"}, + { kEventWindowCollapseAll,"CollapseAll"}, + { kEventWindowExpand,"Expand"}, + { kEventWindowExpanded,"Expanded"}, + { kEventWindowExpandAll,"ExpandAll"}, + { kEventWindowCollapse,"Collapse"}, + { kEventWindowClose,"Close"}, + { kEventWindowClosed,"Closed"}, + { kEventWindowCloseAll,"CloseAll"}, + { kEventWindowZoom,"Zoom"}, + { kEventWindowZoomed,"Zoomed"}, + { kEventWindowZoomAll,"ZoomAll"}, + { kEventWindowContextualMenuSelect,"ContextualMenuSelect"}, + { kEventWindowPathSelect,"PathSelect"}, + { kEventWindowGetIdealSize,"GetIdealSize"}, + { kEventWindowGetMinimumSize,"GetMinimumSize"}, + { kEventWindowGetMaximumSize,"GetMaximumSize"}, + { kEventWindowConstrain,"Constrain"}, + { kEventWindowHandleContentClick,"HandleContentClick"}, + { kEventWindowProxyBeginDrag,"ProxyBeginDra}"}, + { kEventWindowProxyEndDrag,"ProxyEndDrag"}, + { kEventWindowFocusAcquired,"FocusAcquired"}, + { kEventWindowFocusRelinquish,"FocusRelinquish"}, + { kEventWindowDrawFrame,"DrawFrame"}, + { kEventWindowDrawPart,"DrawPart"}, + { kEventWindowGetRegion,"GetRegion"}, + { kEventWindowHitTest,"HitTest"}, + { kEventWindowInit,"Init"}, + { kEventWindowDispose,"Dispose"}, + { kEventWindowDragHilite,"DragHilite"}, + { kEventWindowModified,"Modified"}, + { kEventWindowSetupProxyDragImage,"SetupProxyDragImage"}, + { kEventWindowStateChanged,"StateChanged"}, + { kEventWindowMeasureTitle,"MeasureTitle"}, + { kEventWindowDrawGrowBox,"DrawGrowBox"}, + { kEventWindowGetGrowImageRegion,"GetGrowImageRegion"}, + { kEventWindowPaint,"Paint"}, + { 0, NULL }, +}; + +static MyEventName mouseEventNames [] = { + { kEventMouseMoved, "Moved"}, + { kEventMouseUp, "Up"}, + { kEventMouseDown, "Down"}, + { kEventMouseDragged, "Dragged"}, + { kEventMouseWheelMoved, "WheelMoved"}, + { 0, NULL} +}; + +static MyEventName keyboardEventNames [] = { + { kEventRawKeyDown, "Down"}, + { kEventRawKeyRepeat, "Repeat"}, + { kEventRawKeyUp, "Up"}, + { kEventRawKeyModifiersChanged, "ModifiersChanged"}, + { kEventHotKeyPressed, "HotKeyPressed"}, + { kEventHotKeyReleased, "HotKeyReleased"}, + { 0, NULL} +}; + +static MyEventName appEventNames [] = { + { kEventAppActivated, "Activated"}, + { kEventAppDeactivated, "Deactivated"}, + { kEventAppQuit, "Quit"}, + { kEventAppLaunchNotification, "LaunchNotification"}, + { kEventAppLaunched, "Launched"}, + { kEventAppTerminated, "Terminated"}, + { kEventAppFrontSwitched, "FrontSwitched"}, + { 0, NULL} +}; + +static MyEventName menuEventNames [] = { + { kEventMenuBeginTracking, "BeginTracking"}, + { kEventMenuEndTracking, "EndTracking"}, + { kEventMenuChangeTrackingMode, "ChangeTrackingMode"}, + { kEventMenuOpening, "Opening"}, + { kEventMenuClosed, "Closed"}, + { kEventMenuTargetItem, "TargetItem"}, + { kEventMenuMatchKey, "MatchKey"}, + { kEventMenuEnableItems, "EnableItems"}, + { kEventMenuDispose, "Dispose"}, + { 0, NULL } +}; + +static MyEventName controlEventNames [] = { + { kEventControlInitialize, "Initialize" }, + { kEventControlDispose, "Dispose" }, + { kEventControlGetOptimalBounds, "GetOptimalBounds" }, + { kEventControlHit, "Hit" }, + { kEventControlSimulateHit, "SimulateHit" }, + { kEventControlHitTest, "HitTest" }, + { kEventControlDraw, "Draw" }, + { kEventControlApplyBackground, "ApplyBackground" }, + { kEventControlApplyTextColor, "ApplyTextColor" }, + { kEventControlSetFocusPart, "SetFocusPart" }, + { kEventControlGetFocusPart, "GetFocusPart" }, + { kEventControlActivate, "Activate" }, + { kEventControlDeactivate, "Deactivate" }, + { kEventControlSetCursor, "SetCursor" }, + { kEventControlContextualMenuClick, "ContextualMenuClick" }, + { kEventControlClick, "Click" }, + { kEventControlTrack, "Track" }, + { kEventControlGetScrollToHereStartPoint, "GetScrollToHereStartPoint" }, + { kEventControlGetIndicatorDragConstraint, "GetIndicatorDragConstraint" }, + { kEventControlIndicatorMoved, "IndicatorMoved" }, + { kEventControlGhostingFinished, "GhostingFinished" }, + { kEventControlGetActionProcPart, "GetActionProcPart" }, + { kEventControlGetPartRegion, "GetPartRegion" }, + { kEventControlGetPartBounds, "GetPartBounds" }, + { kEventControlSetData, "SetData" }, + { kEventControlGetData, "GetData" }, + { kEventControlValueFieldChanged, "ValueFieldChanged" }, + { kEventControlAddedSubControl, "AddedSubControl" }, + { kEventControlRemovingSubControl, "RemovingSubControl" }, + { kEventControlBoundsChanged, "BoundsChanged" }, + { kEventControlOwningWindowChanged, "OwningWindowChanged" }, + { kEventControlArbitraryMessage, "ArbitraryMessage" }, + { 0, NULL } +}; + + +static MyEventName commandEventNames [] = { + { kEventCommandProcess, "Process" }, + { kEventCommandUpdateStatus, "UpdateStatus" }, + { 0, NULL } +}; + +static MyEventNameList eventNameList [] = { + { kEventClassWindow, windowEventNames }, + { kEventClassMouse, mouseEventNames }, + { kEventClassKeyboard, keyboardEventNames }, + { kEventClassApplication, appEventNames }, + { kEventClassMenu, menuEventNames }, + { kEventClassControl, controlEventNames }, + { kEventClassCommand, commandEventNames }, + { 0, NULL} +}; + + +MyEventName classicEventNames [] = { + { nullEvent,"nullEvent" }, + { mouseDown,"mouseDown" }, + { mouseUp,"mouseUp" }, + { keyDown,"keyDown" }, + { keyUp,"keyUp" }, + { autoKey,"autoKey" }, + { updateEvt,"updateEvt" }, + { diskEvt,"diskEvt" }, + { activateEvt,"activateEvt" }, + { osEvt,"osEvt" }, + { kHighLevelEvent,"kHighLevelEvent" }, + { 0, NULL } +}; + +char * +CarbonEventToAscii(EventRef eventRef, char * buf) +{ + EventClass eventClass; + EventKind eventKind; + MyEventNameList * list = eventNameList; + MyEventName * names = NULL; + int * iPtr = ( int * )buf; + char * iBuf = buf; + int found = 0; + + eventClass = GetEventClass(eventRef); + eventKind = GetEventKind(eventRef); + + *iPtr = eventClass; + buf [ 4 ] = 0; + strcat(buf, " "); + buf += strlen(buf); + while (list->names && (!names) ) { + 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 ); + } + return iBuf; +} + +char * CarbonEventKindToAscii(EventRef eventRef, char * buf ) +{ + EventClass eventClass; + EventKind eventKind; + MyEventNameList * list = eventNameList; + MyEventName * names = NULL; + int found = 0; + eventClass = GetEventClass(eventRef); + eventKind = GetEventKind(eventRef); + while (list->names && (!names) ) { + if (eventClass == list -> c) { + names = list -> names; + } else { + list++; + } + } + if (names) { + found=0; + while ( names->name && !found ) { + if (eventKind==names->kind) { + sprintf(buf,"%s",names->name); + found=1; + } else { + names++; + } + } + } + if (!found) { + sprintf ( buf,"%d", eventKind ); + } else { + sprintf ( buf,"%d", eventKind ); + } + return buf; +} + +char * ClassicEventToAscii(EventRecord * eventPtr, char * buf ) +{ + 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 (!found) { + sprintf(buf,"%-16d %08x %08x, %s", + eventPtr->what, (int) eventPtr->message, + eventPtr->modifiers, buf); + } + return buf; + +} + +void printPoint(char * tag, Point * p ) +{ + fprintf(stderr,"%s %4d %4d\n", + tag,p->h,p->v ); +} + +void printRect(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 ); +} + +void printRegion(char * tag, RgnHandle rgn ) +{ + Rect r; + GetRegionBounds(rgn,&r); + printRect(tag,&r); +} + +void printWindowTitle(char * tag, WindowRef window ) +{ + Str255 title; + GetWTitle(window,title); + title [ title[0] + 1 ] = 0; + fprintf(stderr, "%s %s\n", tag, title +1 ); +} + +typedef struct { + int msg; + char * name; +} MsgName; + +MsgName msgNames [] = { + { kMenuDrawMsg, "Draw"}, + { kMenuSizeMsg, "Size"}, + { kMenuPopUpMsg, "PopUp"}, + { kMenuCalcItemMsg, "CalcItem" }, + { kMenuThemeSavvyMsg, "ThemeSavvy"}, + { kMenuInitMsg, "Init" }, + { kMenuDisposeMsg, "Dispose" }, + { kMenuFindItemMsg, "FindItem" }, + { kMenuHiliteItemMsg, "HiliteItem" }, + { kMenuDrawItemsMsg, "DrawItems" }, + { -1, NULL } +}; + + +char * +TkMacOSXMenuMessageToAscii(int msg, char * s) +{ + MsgName * msgNamePtr; + for (msgNamePtr = msgNames;msgNamePtr->name;) { + if (msgNamePtr->msg==msg) { + strcpy(s,msgNamePtr->name); + return s; + } else { + msgNamePtr++; + } + } + sprintf(s,"unknown : %d", msg ); + return s; +} + + +char * MouseTrackingResultToAscii(MouseTrackingResult r, char * buf) +{ + MsgName trackingNames [] = { + { kMouseTrackingMousePressed , "MousePressed " }, + { kMouseTrackingMouseReleased , "MouseReleased " }, + { kMouseTrackingMouseExited , "MouseExited " }, + { kMouseTrackingMouseEntered , "MouseEntered " }, + { kMouseTrackingMouseMoved , "MouseMoved " }, + { kMouseTrackingKeyModifiersChanged, "KeyModifiersChanged" }, + { kMouseTrackingUserCancelled , "UserCancelled " }, + { kMouseTrackingTimedOut , "TimedOut " }, + { -1, NULL } + }; + MsgName * namePtr; + for (namePtr=trackingNames;namePtr->name;namePtr++) { + if (namePtr->msg==r) { + strcpy(buf,namePtr->name); + return buf; + } + } + sprintf(buf, "Unknown mouse tracking result : %d", r); + return buf; +} diff --git a/macosx/tkMacOSXDebug.h b/macosx/tkMacOSXDebug.h new file mode 100644 index 0000000..0b3185d --- /dev/null +++ b/macosx/tkMacOSXDebug.h @@ -0,0 +1,69 @@ +/* + * tkMacOSXDebug.h -- + * + * Declarations of Macintosh specific functions for debugging MacOS events, + * regions, etc... + * + * Copyright 2001, Apple Computer, Inc. + * + * 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. + */ + +#ifndef _TKMACDEBUG +#define _TKMACDEBUG +#include <Carbon/Carbon.h> + +char * CarbonEventToAscii(EventRef eventRef, char * buf ); +char * ClassicEventToAscii(EventRecord * eventPtr, char * buf ); + +void printRect(char * tag, Rect * r ); +void printPoint(char * tag, Point * p ); + +void printRegion(char * tag, RgnHandle rgn ); +void printWindowTitle(char * tag, WindowRef window ); +char * TkMacOSXMenuMessageToAscii(int msg, char * s); + +char * MouseTrackingResultToAscii(MouseTrackingResult r, char * buf ); +#endif diff --git a/macosx/tkMacOSXDefault.h b/macosx/tkMacOSXDefault.h new file mode 100644 index 0000000..13a05ce --- /dev/null +++ b/macosx/tkMacOSXDefault.h @@ -0,0 +1,531 @@ +/* + * tkMacOSXDefault.h -- + * + * This file defines the defaults for all options for all of + * the Tk widgets. + * + * Copyright (c) 1991-1994 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * 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.2 2002/08/31 06:12:29 das Exp $ + */ + +#ifndef _TKMACDEFAULT +#define _TKMACDEFAULT + +/* + * The definitions below provide symbolic names for the default colors. + * NORMAL_BG - Normal background color. + * ACTIVE_BG - Background color when widget is active. + * SELECT_BG - Background color for selected text. + * SELECT_FG - Foreground color for selected text. + * TROUGH - Background color for troughs in scales and scrollbars. + * INDICATOR - Color for indicator when button is selected. + * 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 TROUGH "#c3c3c3" +#define INDICATOR "#b03060" +#define DISABLED "#a3a3a3" + +/* + * Defaults for labels, buttons, checkbuttons, and radiobuttons: + */ + +#define DEF_BUTTON_ANCHOR "center" +#define DEF_BUTTON_ACTIVE_BG_COLOR "systemButtonText" +#define DEF_BUTTON_ACTIVE_BG_MONO BLACK +#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 WHITE +#define DEF_BUTTON_BG_MONO WHITE +#define DEF_BUTTON_BITMAP "" +#define DEF_BUTTON_BORDER_WIDTH "2" +#define DEF_BUTTON_CURSOR "" +#define DEF_BUTTON_COMMAND "" +#define DEF_BUTTON_COMPOUND "none" +#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_CHKRAD_FG DEF_BUTTON_FG +#define DEF_BUTTON_FONT "system" +#define DEF_BUTTON_HEIGHT "0" +#define DEF_BUTTON_HIGHLIGHT_BG_COLOR DEF_BUTTON_BG_COLOR +#define DEF_BUTTON_HIGHLIGHT_BG_MONO DEF_BUTTON_BG_MONO +#define DEF_BUTTON_HIGHLIGHT "systemButtonFrame" +#define DEF_LABEL_HIGHLIGHT_WIDTH "0" +#define DEF_BUTTON_HIGHLIGHT_WIDTH "4" +#define DEF_BUTTON_IMAGE (char *) NULL +#define DEF_BUTTON_INDICATOR "1" +#define DEF_BUTTON_JUSTIFY "center" +#define DEF_BUTTON_OFF_VALUE "0" +#define DEF_BUTTON_ON_VALUE "1" +#define DEF_BUTTON_OVER_RELIEF "" +#define DEF_BUTTON_PADX "12" +#define DEF_LABCHKRAD_PADX "1" +#define DEF_BUTTON_PADY "3" +#define DEF_LABCHKRAD_PADY "1" +#define DEF_BUTTON_RELIEF "flat" +#define DEF_LABCHKRAD_RELIEF "flat" +#define DEF_BUTTON_REPEAT_DELAY "0" +#define DEF_BUTTON_REPEAT_INTERVAL "0" +#define DEF_BUTTON_SELECT_COLOR INDICATOR +#define DEF_BUTTON_SELECT_MONO BLACK +#define DEF_BUTTON_SELECT_IMAGE (char *) NULL +#define DEF_BUTTON_STATE "normal" +#define DEF_LABEL_TAKE_FOCUS "0" +#define DEF_BUTTON_TAKE_FOCUS (char *) NULL +#define DEF_BUTTON_TEXT "" +#define DEF_BUTTON_TEXT_VARIABLE "" +#define DEF_BUTTON_UNDERLINE "-1" +#define DEF_BUTTON_VALUE "" +#define DEF_BUTTON_WIDTH "0" +#define DEF_BUTTON_WRAP_LENGTH "0" +#define DEF_RADIOBUTTON_VARIABLE "selectedButton" +#define DEF_CHECKBUTTON_VARIABLE "" + +/* + * Defaults for canvases: + */ + +#define DEF_CANVAS_BG_COLOR NORMAL_BG +#define DEF_CANVAS_BG_MONO WHITE +#define DEF_CANVAS_BORDER_WIDTH "0" +#define DEF_CANVAS_CLOSE_ENOUGH "1" +#define DEF_CANVAS_CONFINE "1" +#define DEF_CANVAS_CURSOR "" +#define DEF_CANVAS_HEIGHT "7c" +#define DEF_CANVAS_HIGHLIGHT_BG NORMAL_BG +#define DEF_CANVAS_HIGHLIGHT BLACK +#define DEF_CANVAS_HIGHLIGHT_WIDTH "3" +#define DEF_CANVAS_INSERT_BG BLACK +#define DEF_CANVAS_INSERT_BD_COLOR "0" +#define DEF_CANVAS_INSERT_BD_MONO "0" +#define DEF_CANVAS_INSERT_OFF_TIME "300" +#define DEF_CANVAS_INSERT_ON_TIME "600" +#define DEF_CANVAS_INSERT_WIDTH "2" +#define DEF_CANVAS_RELIEF "flat" +#define DEF_CANVAS_SCROLL_REGION "" +#define DEF_CANVAS_SELECT_COLOR SELECT_BG +#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_MONO WHITE +#define DEF_CANVAS_TAKE_FOCUS (char *) NULL +#define DEF_CANVAS_WIDTH "10c" +#define DEF_CANVAS_X_SCROLL_CMD "" +#define DEF_CANVAS_X_SCROLL_INCREMENT "0" +#define DEF_CANVAS_Y_SCROLL_CMD "" +#define DEF_CANVAS_Y_SCROLL_INCREMENT "0" + +/* + * Defaults for entries: + */ + +#define DEF_ENTRY_BG_COLOR NORMAL_BG +#define DEF_ENTRY_BG_MONO WHITE +/* #define DEF_ENTRY_BORDER_WIDTH "2" */ +#define DEF_ENTRY_BORDER_WIDTH "1" +#define DEF_ENTRY_CURSOR "xterm" +#define DEF_ENTRY_DISABLED_BG_COLOR NORMAL_BG +#define DEF_ENTRY_DISABLED_BG_MONO WHITE +#define DEF_ENTRY_DISABLED_FG DISABLED +#define DEF_ENTRY_EXPORT_SELECTION "1" +#define DEF_ENTRY_FONT "Helvetica 12" +#define DEF_ENTRY_FG BLACK +#define DEF_ENTRY_HIGHLIGHT_BG NORMAL_BG +#define DEF_ENTRY_HIGHLIGHT BLACK +/* #define DEF_ENTRY_HIGHLIGHT_WIDTH "3" */ +#define DEF_ENTRY_HIGHLIGHT_WIDTH "0" +#define DEF_ENTRY_INSERT_BG BLACK +#define DEF_ENTRY_INSERT_BD_COLOR "0" +#define DEF_ENTRY_INSERT_BD_MONO "0" +#define DEF_ENTRY_INSERT_OFF_TIME "300" +#define DEF_ENTRY_INSERT_ON_TIME "600" +/* #define DEF_ENTRY_INSERT_WIDTH "2" */ +#define DEF_ENTRY_INSERT_WIDTH "1" +#define DEF_ENTRY_JUSTIFY "left" +#define DEF_ENTRY_READONLY_BG_COLOR NORMAL_BG +#define DEF_ENTRY_READONLY_BG_MONO WHITE +/* #define DEF_ENTRY_RELIEF "sunken" */ +#define DEF_ENTRY_RELIEF "solid" +#define DEF_ENTRY_SCROLL_COMMAND "" +#define DEF_ENTRY_SELECT_COLOR SELECT_BG +#define DEF_ENTRY_SELECT_MONO BLACK +#define DEF_ENTRY_SELECT_BD_COLOR "1" +#define DEF_ENTRY_SELECT_BD_MONO "0" +#define DEF_ENTRY_SELECT_FG_COLOR SELECT_FG +#define DEF_ENTRY_SELECT_FG_MONO WHITE +#define DEF_ENTRY_SHOW (char *) NULL +#define DEF_ENTRY_STATE "normal" +#define DEF_ENTRY_TAKE_FOCUS (char *) NULL +#define DEF_ENTRY_TEXT_VARIABLE "" +#define DEF_ENTRY_WIDTH "20" + +/* + * Defaults for frames: + */ + +#define DEF_FRAME_BG_COLOR NORMAL_BG +#define DEF_FRAME_BG_MONO WHITE +#define DEF_FRAME_BORDER_WIDTH "0" +#define DEF_FRAME_CLASS "Frame" +#define DEF_FRAME_COLORMAP "" +#define DEF_FRAME_CONTAINER "0" +#define DEF_FRAME_CURSOR "" +#define DEF_FRAME_HEIGHT "0" +#define DEF_FRAME_HIGHLIGHT_BG NORMAL_BG +#define DEF_FRAME_HIGHLIGHT BLACK +#define DEF_FRAME_HIGHLIGHT_WIDTH "0" +#define DEF_FRAME_PADX "0" +#define DEF_FRAME_PADY "0" +#define DEF_FRAME_RELIEF "flat" +#define DEF_FRAME_TAKE_FOCUS "0" +#define DEF_FRAME_VISUAL "" +#define DEF_FRAME_WIDTH "0" + +/* + * Defaults for labelframes: + */ + +#define DEF_LABELFRAME_BORDER_WIDTH "2" +#define DEF_LABELFRAME_CLASS "Labelframe" +#define DEF_LABELFRAME_RELIEF "groove" +#define DEF_LABELFRAME_FG "systemButtonText" +#define DEF_LABELFRAME_FONT "system" +#define DEF_LABELFRAME_TEXT "" +#define DEF_LABELFRAME_LABELANCHOR "nw" + +/* + * Defaults for listboxes: + */ + +#define DEF_LISTBOX_ACTIVE_STYLE "underline" +#define DEF_LISTBOX_BG_COLOR NORMAL_BG +#define DEF_LISTBOX_BG_MONO WHITE +#define DEF_LISTBOX_BORDER_WIDTH "1" +#define DEF_LISTBOX_CURSOR "" +#define DEF_LISTBOX_DISABLED_FG DISABLED +#define DEF_LISTBOX_EXPORT_SELECTION "1" +#define DEF_LISTBOX_FONT "application" +#define DEF_LISTBOX_FG BLACK +#define DEF_LISTBOX_HEIGHT "10" +#define DEF_LISTBOX_HIGHLIGHT_BG NORMAL_BG +#define DEF_LISTBOX_HIGHLIGHT BLACK +#define DEF_LISTBOX_HIGHLIGHT_WIDTH "0" +#define DEF_LISTBOX_RELIEF "solid" +#define DEF_LISTBOX_SCROLL_COMMAND "" +#define DEF_LISTBOX_LIST_VARIABLE "" +#define DEF_LISTBOX_SELECT_COLOR SELECT_BG +#define DEF_LISTBOX_SELECT_MONO BLACK +#define DEF_LISTBOX_SELECT_BD "0" +#define DEF_LISTBOX_SELECT_FG_COLOR SELECT_FG +#define DEF_LISTBOX_SELECT_FG_MONO WHITE +#define DEF_LISTBOX_SELECT_MODE "browse" +#define DEF_LISTBOX_SET_GRID "0" +#define DEF_LISTBOX_STATE "normal" +#define DEF_LISTBOX_TAKE_FOCUS (char *) NULL +#define DEF_LISTBOX_WIDTH "20" + +/* + * Defaults for individual entries of menus: + */ + +#define DEF_MENU_ENTRY_ACTIVE_BG (char *) NULL +#define DEF_MENU_ENTRY_ACTIVE_FG (char *) NULL +#define DEF_MENU_ENTRY_ACCELERATOR (char *) NULL +#define DEF_MENU_ENTRY_BG (char *) NULL +#define DEF_MENU_ENTRY_BITMAP None +#define DEF_MENU_ENTRY_COLUMN_BREAK "0" +#define DEF_MENU_ENTRY_COMMAND (char *) NULL +#define DEF_MENU_ENTRY_COMPOUND "none" +#define DEF_MENU_ENTRY_FG (char *) NULL +#define DEF_MENU_ENTRY_FONT (char *) NULL +#define DEF_MENU_ENTRY_HIDE_MARGIN "0" +#define DEF_MENU_ENTRY_IMAGE (char *) NULL +#define DEF_MENU_ENTRY_INDICATOR "1" +#define DEF_MENU_ENTRY_LABEL (char *) NULL +#define DEF_MENU_ENTRY_MENU (char *) NULL +#define DEF_MENU_ENTRY_OFF_VALUE "0" +#define DEF_MENU_ENTRY_ON_VALUE "1" +#define DEF_MENU_ENTRY_SELECT_IMAGE (char *) NULL +#define DEF_MENU_ENTRY_STATE "normal" +#define DEF_MENU_ENTRY_VALUE (char *) NULL +#define DEF_MENU_ENTRY_CHECK_VARIABLE (char *) NULL +#define DEF_MENU_ENTRY_RADIO_VARIABLE "selectedButton" +#define DEF_MENU_ENTRY_SELECT (char *) NULL +#define DEF_MENU_ENTRY_UNDERLINE "-1" + +/* + * Defaults for menus overall: + */ + +#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_MONO WHITE +#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_MONO "" +#define DEF_MENU_FONT "system" +#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_MONO BLACK +#define DEF_MENU_TAKE_FOCUS "0" +#define DEF_MENU_TEAROFF "1" +#define DEF_MENU_TEAROFF_CMD (char *) NULL +#define DEF_MENU_TITLE "" +#define DEF_MENU_TYPE "normal" + +/* + * Defaults for menubuttons: + */ + +#define DEF_MENUBUTTON_ANCHOR "center" +#define DEF_MENUBUTTON_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_MENUBUTTON_ACTIVE_BG_MONO BLACK +#define DEF_MENUBUTTON_ACTIVE_FG_COLOR BLACK +#define DEF_MENUBUTTON_ACTIVE_FG_MONO WHITE +#define DEF_MENUBUTTON_BG_COLOR NORMAL_BG +#define DEF_MENUBUTTON_BG_MONO WHITE +#define DEF_MENUBUTTON_BITMAP "" +#define DEF_MENUBUTTON_BORDER_WIDTH "2" +#define DEF_MENUBUTTON_CURSOR "" +#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_FG BLACK +#define DEF_MENUBUTTON_HEIGHT "0" +#define DEF_MENUBUTTON_HIGHLIGHT_BG_COLOR DEF_MENUBUTTON_BG_COLOR +#define DEF_MENUBUTTON_HIGHLIGHT_BG_MONO DEF_MENUBUTTON_BG_MONO +#define DEF_MENUBUTTON_HIGHLIGHT BLACK +#define DEF_MENUBUTTON_HIGHLIGHT_WIDTH "0" +#define DEF_MENUBUTTON_IMAGE (char *) NULL +#define DEF_MENUBUTTON_INDICATOR "0" +/* #define DEF_MENUBUTTON_JUSTIFY "center" */ +#define DEF_MENUBUTTON_JUSTIFY "left" +#define DEF_MENUBUTTON_MENU "" +#define DEF_MENUBUTTON_PADX "4p" +#define DEF_MENUBUTTON_PADY "3p" +#define DEF_MENUBUTTON_RELIEF "flat" +#define DEF_MENUBUTTON_STATE "normal" +#define DEF_MENUBUTTON_TAKE_FOCUS "0" +#define DEF_MENUBUTTON_TEXT "" +#define DEF_MENUBUTTON_TEXT_VARIABLE "" +#define DEF_MENUBUTTON_UNDERLINE "-1" +#define DEF_MENUBUTTON_WIDTH "0" +#define DEF_MENUBUTTON_WRAP_LENGTH "0" + +/* + * Defaults for messages: + */ + +#define DEF_MESSAGE_ANCHOR "center" +#define DEF_MESSAGE_ASPECT "150" +#define DEF_MESSAGE_BG_COLOR NORMAL_BG +#define DEF_MESSAGE_BG_MONO WHITE +#define DEF_MESSAGE_BORDER_WIDTH "2" +#define DEF_MESSAGE_CURSOR "" +#define DEF_MESSAGE_FG BLACK +#define DEF_MESSAGE_FONT "system" +#define DEF_MESSAGE_HIGHLIGHT_BG NORMAL_BG +#define DEF_MESSAGE_HIGHLIGHT BLACK +#define DEF_MESSAGE_HIGHLIGHT_WIDTH "0" +#define DEF_MESSAGE_JUSTIFY "left" +#define DEF_MESSAGE_PADX "-1" +#define DEF_MESSAGE_PADY "-1" +#define DEF_MESSAGE_RELIEF "flat" +#define DEF_MESSAGE_TAKE_FOCUS "0" +#define DEF_MESSAGE_TEXT "" +#define DEF_MESSAGE_TEXT_VARIABLE "" +#define DEF_MESSAGE_WIDTH "0" +/* + * Defaults for panedwindows + */ + +#define DEF_PANEDWINDOW_BG_COLOR NORMAL_BG +#define DEF_PANEDWINDOW_BG_MONO WHITE +#define DEF_PANEDWINDOW_BORDERWIDTH "2" +#define DEF_PANEDWINDOW_CURSOR "" +#define DEF_PANEDWINDOW_HANDLEPAD "8" +#define DEF_PANEDWINDOW_HANDLESIZE "8" +#define DEF_PANEDWINDOW_HEIGHT "" +#define DEF_PANEDWINDOW_OPAQUERESIZE "0" +#define DEF_PANEDWINDOW_ORIENT "horizontal" +#define DEF_PANEDWINDOW_RELIEF "flat" +#define DEF_PANEDWINDOW_SASHCURSOR "" +#define DEF_PANEDWINDOW_SASHPAD "2" +#define DEF_PANEDWINDOW_SASHRELIEF "raised" +#define DEF_PANEDWINDOW_SASHWIDTH "2" +#define DEF_PANEDWINDOW_SHOWHANDLE "1" +#define DEF_PANEDWINDOW_WIDTH "" + +/* + * Defaults for panedwindow panes + */ + +#define DEF_PANEDWINDOW_PANE_AFTER "" +#define DEF_PANEDWINDOW_PANE_BEFORE "" +#define DEF_PANEDWINDOW_PANE_HEIGHT "" +#define DEF_PANEDWINDOW_PANE_MINSIZE "0" +#define DEF_PANEDWINDOW_PANE_PADX "0" +#define DEF_PANEDWINDOW_PANE_PADY "0" +#define DEF_PANEDWINDOW_PANE_STICKY "nsew" +#define DEF_PANEDWINDOW_PANE_WIDTH "" + +/* + * Defaults for scales: + */ + +#define DEF_SCALE_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_SCALE_ACTIVE_BG_MONO BLACK +#define DEF_SCALE_BG_COLOR NORMAL_BG +#define DEF_SCALE_BG_MONO WHITE +#define DEF_SCALE_BIG_INCREMENT "0" +#define DEF_SCALE_BORDER_WIDTH "2" +#define DEF_SCALE_COMMAND "" +#define DEF_SCALE_CURSOR "" +#define DEF_SCALE_DIGITS "0" +#define DEF_SCALE_FONT "system" +#define DEF_SCALE_FG_COLOR BLACK +#define DEF_SCALE_FG_MONO BLACK +#define DEF_SCALE_FROM "0" +#define DEF_SCALE_HIGHLIGHT_BG_COLOR DEF_SCALE_BG_COLOR +#define DEF_SCALE_HIGHLIGHT_BG_MONO DEF_SCALE_BG_MONO +#define DEF_SCALE_HIGHLIGHT BLACK +#define DEF_SCALE_HIGHLIGHT_WIDTH "0" +#define DEF_SCALE_LABEL "" +#define DEF_SCALE_LENGTH "100" +#define DEF_SCALE_ORIENT "vertical" +#define DEF_SCALE_RELIEF "flat" +#define DEF_SCALE_REPEAT_DELAY "300" +#define DEF_SCALE_REPEAT_INTERVAL "100" +#define DEF_SCALE_RESOLUTION "1" +#define DEF_SCALE_TROUGH_COLOR TROUGH +#define DEF_SCALE_TROUGH_MONO WHITE +#define DEF_SCALE_SHOW_VALUE "1" +#define DEF_SCALE_SLIDER_LENGTH "30" +#define DEF_SCALE_SLIDER_RELIEF "raised" +#define DEF_SCALE_STATE "normal" +#define DEF_SCALE_TAKE_FOCUS (char *) NULL +#define DEF_SCALE_TICK_INTERVAL "0" +#define DEF_SCALE_TO "100" +#define DEF_SCALE_VARIABLE "" +#define DEF_SCALE_WIDTH "15" + +/* + * Defaults for scrollbars: + */ + +#define DEF_SCROLLBAR_ACTIVE_BG_COLOR ACTIVE_BG +#define DEF_SCROLLBAR_ACTIVE_BG_MONO BLACK +#define DEF_SCROLLBAR_ACTIVE_RELIEF "raised" +#define DEF_SCROLLBAR_BG_COLOR NORMAL_BG +#define DEF_SCROLLBAR_BG_MONO WHITE +/* #define DEF_SCROLLBAR_BORDER_WIDTH "2" */ +#define DEF_SCROLLBAR_BORDER_WIDTH "0" +#define DEF_SCROLLBAR_COMMAND "" +#define DEF_SCROLLBAR_CURSOR "" +#define DEF_SCROLLBAR_EL_BORDER_WIDTH "-1" +#define DEF_SCROLLBAR_HIGHLIGHT_BG NORMAL_BG +#define DEF_SCROLLBAR_HIGHLIGHT BLACK +/* #define DEF_SCROLLBAR_HIGHLIGHT_WIDTH "2" */ +#define DEF_SCROLLBAR_HIGHLIGHT_WIDTH "0" +#define DEF_SCROLLBAR_JUMP "0" +#define DEF_SCROLLBAR_ORIENT "vertical" +/*#define DEF_SCROLLBAR_RELIEF "sunken" */ +#define DEF_SCROLLBAR_RELIEF "flat" +#define DEF_SCROLLBAR_REPEAT_DELAY "300" +#define DEF_SCROLLBAR_REPEAT_INTERVAL "100" +#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" + +/* + * Defaults for texts: + */ + +#define DEF_TEXT_AUTO_SEPARATORS "1" +#define DEF_TEXT_BG_COLOR NORMAL_BG +#define DEF_TEXT_BG_MONO WHITE +#define DEF_TEXT_BORDER_WIDTH "0" +#define DEF_TEXT_CURSOR "xterm" +#define DEF_TEXT_FG BLACK +#define DEF_TEXT_EXPORT_SELECTION "1" +#define DEF_TEXT_FONT "Courier 12" +#define DEF_TEXT_HEIGHT "24" +#define DEF_TEXT_HIGHLIGHT_BG NORMAL_BG +#define DEF_TEXT_HIGHLIGHT BLACK +#define DEF_TEXT_HIGHLIGHT_WIDTH "3" +#define DEF_TEXT_INSERT_BG BLACK +#define DEF_TEXT_INSERT_BD_COLOR "0" +#define DEF_TEXT_INSERT_BD_MONO "0" +#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_PADX "1" +#define DEF_TEXT_PADY "1" +#define DEF_TEXT_RELIEF "flat" +#define DEF_TEXT_SELECT_COLOR SELECT_BG +#define DEF_TEXT_SELECT_MONO BLACK +#define DEF_TEXT_SELECT_BD_COLOR "1" +#define DEF_TEXT_SELECT_BD_MONO "0" +#define DEF_TEXT_SELECT_FG_COLOR SELECT_FG +#define DEF_TEXT_SELECT_FG_MONO WHITE +#define DEF_TEXT_SELECT_RELIEF "solid" +#define DEF_TEXT_SET_GRID "0" +#define DEF_TEXT_SPACING1 "0" +#define DEF_TEXT_SPACING2 "0" +#define DEF_TEXT_SPACING3 "0" +#define DEF_TEXT_STATE "normal" +#define DEF_TEXT_TABS "" +#define DEF_TEXT_TAKE_FOCUS (char *) NULL +#define DEF_TEXT_UNDO "0" +#define DEF_TEXT_WIDTH "80" +#define DEF_TEXT_WRAP "char" +#define DEF_TEXT_XSCROLL_COMMAND "" +#define DEF_TEXT_YSCROLL_COMMAND "" + +/* + * Defaults for canvas text: + */ + +#define DEF_CANVTEXT_FONT "Helvetica 12" + +/* + * Defaults for toplevels (most of the defaults for frames also apply + * to toplevels): + */ + +#define DEF_TOPLEVEL_CLASS "Toplevel" +#define DEF_TOPLEVEL_MENU "" +#define DEF_TOPLEVEL_SCREEN "" +#define DEF_TOPLEVEL_USE "" + +#endif /* _TKMACDEFAULT */ diff --git a/macosx/tkMacOSXDialog.c b/macosx/tkMacOSXDialog.c new file mode 100644 index 0000000..3decc8a --- /dev/null +++ b/macosx/tkMacOSXDialog.c @@ -0,0 +1,1229 @@ +/* + * tkMacOSXDialog.c -- + * + * Contains the Mac implementation of the common dialog boxes. + * + * Copyright (c) 1996-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * 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.2 2002/08/31 06:12:29 das Exp $ + */ +#include <Carbon/Carbon.h> + +#include "tkPort.h" +#include "tkInt.h" +#include "tkMacOSXUtil.h" +#include "tkMacOSXInt.h" +#include "tkFileFilter.h" + +#ifndef StrLength +#define StrLength(s) (*((unsigned char *) (s))) +#endif +#ifndef StrBody +#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 MATCHED 0 +#define UNMATCHED 1 + +#define TK_DEFAULT_ABOUT 128 + +/* + * The following structure is used in the GetFileName() function. It stored + * information about the file dialog and the file filters. + */ +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. */ + int usePopup; /* True if we show the popup menu (this + * is an open operation and the + * -filetypes option is set). */ +} OpenFileData; + + +static Boolean MatchOneType _ANSI_ARGS_((StringPtr fileNamePtr, OSType fileType, + OpenFileData *myofdPtr, FileFilter *filterPtr)); +static pascal Boolean OpenFileFilterProc(AEDesc* theItem, void* info, + NavCallBackUserData callBackUD, + NavFilterModes filterMode ); +pascal void OpenEventProc(NavEventCallbackMessage callBackSelector, + NavCBRecPtr callBackParms, + NavCallBackUserData callBackUD ); +static void InitFileDialogs(); +static int NavServicesGetFile(Tcl_Interp *interp, OpenFileData *ofd, + AEDesc *initialDescPtr, + unsigned char *initialFile, AEDescList *selectDescPtr, + StringPtr title, StringPtr message, int multiple, int isOpen); +static int HandleInitialDirectory (Tcl_Interp *interp, + char *initialFile, char *initialDir, + FSRef *dirRef, + AEDescList *selectDescPtr, + AEDesc *dirDescPtr); + +/* + * Have we initialized the file dialog subsystem + */ + +static int fileDlgInited = 0; + +/* + * Filter and hook functions used by the tk_getOpenFile and tk_getSaveFile + * commands. + */ + +NavObjectFilterUPP openFileFilterUPP; +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. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * 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. */ +{ + Tk_Window parent; + char *title; + int i, picked, srcRead, dstWrote; + ColorPickerInfo cpinfo; + static int inited = 0; + static RGBColor in; + static CONST char *optionStrings[] = { + "-initialcolor", "-parent", "-title", NULL + }; + enum options { + 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.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; + + 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); + Tcl_AppendResult(interp, "value for \"", option, "\" missing", + (char *) NULL); + return TCL_ERROR; + } + value = Tcl_GetStringFromObj(objv[i + 1], NULL); + + switch ((enum options) index) { + case COLOR_INITIAL: { + XColor *colorPtr; + + colorPtr = Tk_GetColor(interp, parent, value); + if (colorPtr == NULL) { + return TCL_ERROR; + } + in.red = colorPtr->red; + in.green = colorPtr->green; + in.blue = colorPtr->blue; + Tk_FreeColor(colorPtr); + break; + } + case COLOR_PARENT: { + parent = Tk_NameToWindow(interp, value, parent); + if (parent == NULL) { + return TCL_ERROR; + } + break; + } + case COLOR_TITLE: { + title = value; + break; + } + } + } + + + cpinfo.theColor.profile = 0L; + 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 = NULL; + + /* This doesn't seem to actually set the title! */ + Tcl_UtfToExternal(NULL, NULL, 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; + picked = 1; + } + + if (picked != 0) { + char result[32]; + + sprintf(result, "#%02x%02x%02x", in.red >> 8, in.green >> 8, + in.blue >> 8); + Tcl_AppendResult(interp, result, NULL); + } + + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * Tk_GetOpenFileObjCmd -- + * + * 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. + * + * Side effects: + * 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. */ +{ + int i, result, multiple; + OpenFileData ofd; + Tk_Window parent; + Str255 message, title; + 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 + }; + enum openOptions { + 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[0] = 0; + message[0] = 0; + + TkInitFileFilters(&ofd.fl); + + 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; + int srcRead, dstWrote; + + 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); + Tcl_AppendResult(interp, "value for \"", string, "\" missing", + (char *) NULL); + result = TCL_ERROR; + goto end; + } + + switch (index) { + case OPEN_DEFAULT: + break; + case OPEN_FILETYPES: + choice = Tcl_GetStringFromObj(objv[i + 1], NULL); + if (TkGetFileFilters(interp, &ofd.fl, choice, 0) + != TCL_OK) { + result = TCL_ERROR; + goto end; + } + break; + case OPEN_INITDIR: + initialDir = Tcl_GetStringFromObj(objv[i + 1], NULL); + break; + case OPEN_INITFILE: + initialFile = Tcl_GetStringFromObj(objv[i + 1], NULL); + break; + case OPEN_MESSAGE: + choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); + Tcl_UtfToExternal(NULL, TkMacOSXCarbonEncoding, choice, choiceLen, + 0, NULL, StrBody(message), 255, + &srcRead, &dstWrote, NULL); + message[0] = dstWrote; + 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); + if (parent == NULL) { + result = TCL_ERROR; + goto end; + } + break; + case OPEN_TITLE: + choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); + Tcl_UtfToExternal(NULL, TkMacOSXCarbonEncoding, choice, choiceLen, + 0, NULL, StrBody(title), 255, + &srcRead, &dstWrote, NULL); + title[0] = dstWrote; + break; + } + } + + if (HandleInitialDirectory(interp, initialFile, initialDir, &dirRef, + &selectDesc, &initialDesc) != TCL_OK) { + result = TCL_ERROR; + goto end; + } + + if (initialDesc.descriptorType == typeFSRef) { + initialPtr = &initialDesc; + } + result = NavServicesGetFile(interp, &ofd, initialPtr, + NULL, &selectDesc, + title, message, multiple, OPEN_FILE); + + end: + TkFreeFileFilters(&ofd.fl); + AEDisposeDesc(&initialDesc); + AEDisposeDesc(&selectDesc); + + return result; +} + +/* + *---------------------------------------------------------------------- + * + * Tk_GetSaveFileObjCmd -- + * + * Same as Tk_GetOpenFileCmd but opens a "save file" dialog box + * instead + * + * Results: + * A standard Tcl result. + * + * Side effects: + * 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. */ +{ + int i, result; + Str255 initialFile; + Tk_Window parent; + AEDesc initialDesc = {typeNull, NULL}; + AEDesc *initialPtr = NULL; + FSRef dirRef; + Str255 title, message; + OpenFileData ofd; + 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 + }; + + if (!fileDlgInited) { + InitFileDialogs(); + } + + result = TCL_ERROR; + parent = (Tk_Window) clientData; + StrLength(initialFile) = 0; + title[0] = 0; + message[0] = 0; + + for (i = 1; i < objc; i += 2) { + char *choice; + int index, choiceLen; + char *string; + Tcl_DString ds; + int srcRead, dstWrote; + + if (Tcl_GetIndexFromObj(interp, objv[i], saveOptionStrings, "option", + TCL_EXACT, &index) != TCL_OK) { + return TCL_ERROR; + } + if (i + 1 == objc) { + string = Tcl_GetStringFromObj(objv[i], NULL); + Tcl_AppendResult(interp, "value for \"", string, "\" missing", + (char *) NULL); + return TCL_ERROR; + } + switch (index) { + case SAVE_DEFAULT: + break; + case SAVE_FILETYPES: + /* Currently unimplemented - what would we do here anyway? */ + break; + case SAVE_INITDIR: + choice = Tcl_GetStringFromObj(objv[i + 1], NULL); + if (HandleInitialDirectory(interp, NULL, choice, &dirRef, + NULL, &initialDesc) != TCL_OK) { + result = TCL_ERROR; + goto end; + } + break; + case SAVE_INITFILE: + choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); + if (Tcl_TranslateFileName(interp, choice, &ds) == NULL) { + result = TCL_ERROR; + goto end; + } + Tcl_UtfToExternal(NULL, TkMacOSXCarbonEncoding, Tcl_DStringValue(&ds), + Tcl_DStringLength(&ds), 0, NULL, + StrBody(initialFile), 255, &srcRead, &dstWrote, NULL); + StrLength(initialFile) = (unsigned char) dstWrote; + Tcl_DStringFree(&ds); + break; + case SAVE_MESSAGE: + choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); + Tcl_UtfToExternal(NULL, TkMacOSXCarbonEncoding, choice, choiceLen, + 0, NULL, StrBody(message), 255, + &srcRead, &dstWrote, NULL); + StrLength(message) = (unsigned char) dstWrote; + break; + case SAVE_PARENT: + choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); + parent = Tk_NameToWindow(interp, choice, parent); + if (parent == NULL) { + result = TCL_ERROR; + goto end; + } + break; + case SAVE_TITLE: + choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); + Tcl_UtfToExternal(NULL, TkMacOSXCarbonEncoding, choice, choiceLen, + 0, NULL, StrBody(title), 255, + &srcRead, &dstWrote, NULL); + StrLength(title) = (unsigned char) dstWrote; + 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); + + return result; +} + +/* + *---------------------------------------------------------------------- + * + * Tk_ChooseDirectoryObjCmd -- + * + * 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. + * + * Side effects: + * A modal dialog window is created. Tcl_SetServiceMode() is + * called to allow background events to be processed + * + *---------------------------------------------------------------------- + */ + +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. */ +{ + int i, result; + Tk_Window parent; + AEDesc initialDesc = {typeNull, NULL}; + AEDesc *initialPtr = NULL; + FSRef dirRef; + Str255 message, title; + int srcRead, dstWrote; + OpenFileData ofd; + static CONST char *chooseOptionStrings[] = { + "-initialdir", "-message", "-mustexist", "-parent", "-title", NULL + }; + enum chooseOptions { + 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[0] = 0; + message[0] = 0; + + for (i = 1; i < objc; i += 2) { + char *choice; + int index, choiceLen; + char *string; + + if (Tcl_GetIndexFromObj(interp, objv[i], chooseOptionStrings, "option", + TCL_EXACT, &index) != TCL_OK) { + return TCL_ERROR; + } + if (i + 1 == objc) { + string = Tcl_GetStringFromObj(objv[i], NULL); + Tcl_AppendResult(interp, "value for \"", string, "\" missing", + (char *) NULL); + return TCL_ERROR; + } + switch (index) { + case CHOOSE_INITDIR: + choice = Tcl_GetStringFromObj(objv[i + 1], NULL); + if (HandleInitialDirectory(interp, NULL, choice, &dirRef, + NULL, &initialDesc) != TCL_OK) { + result = TCL_ERROR; + goto end; + } + break; + case CHOOSE_MESSAGE: + choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); + Tcl_UtfToExternal(NULL, TkMacOSXCarbonEncoding, choice, choiceLen, + 0, NULL, StrBody(message), 255, + &srcRead, &dstWrote, NULL); + StrLength(message) = (unsigned char) dstWrote; + break; + case CHOOSE_PARENT: + choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); + parent = Tk_NameToWindow(interp, choice, parent); + if (parent == NULL) { + result = TCL_ERROR; + goto end; + } + break; + case CHOOSE_TITLE: + choice = Tcl_GetStringFromObj(objv[i + 1], &choiceLen); + Tcl_UtfToExternal(NULL, TkMacOSXCarbonEncoding, choice, choiceLen, + 0, NULL, StrBody(title), 255, + &srcRead, &dstWrote, NULL); + StrLength(title) = (unsigned char) dstWrote; + 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); + + return result; +} + +int +HandleInitialDirectory ( + Tcl_Interp *interp, + char *initialFile, + char *initialDir, + FSRef *dirRef, + AEDescList *selectDescPtr, + AEDesc *dirDescPtr) +{ + Tcl_DString ds; + OSErr err; + Boolean isDirectory; + char *dirName = NULL; + int result = TCL_OK; + + if (initialDir != NULL) { + dirName = Tcl_TranslateFileName(interp, initialDir, &ds); + if (dirName == NULL) { + return TCL_ERROR; + } + + err = FSPathMakeRef(dirName, + dirRef, &isDirectory); + + if (err != noErr) { + Tcl_AppendResult(interp, "bad directory \"", + initialDir, "\"", NULL); + result = TCL_ERROR; + 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); + } + + if (initialFile != NULL && selectDescPtr != NULL) { + FSRef fileRef; + AEDesc fileDesc; + char *namePtr; + + if (initialDir != NULL) { + Tcl_DStringAppend(&ds, "/", 1); + Tcl_DStringAppend(&ds, initialFile, -1); + namePtr = Tcl_DStringValue(&ds); + } else { + namePtr = initialFile; + } + + AECreateList(NULL, 0, false, selectDescPtr); + + err = FSPathMakeRef(namePtr, &fileRef, &isDirectory); + if (err != noErr) { + Tcl_AppendResult(interp, "bad initialfile \"", initialFile, + "\" file does not exist.", NULL); + return TCL_ERROR; + } + AECreateDesc(typeFSRef, &fileRef, sizeof(fileRef), &fileDesc); + AEPutDesc(selectDescPtr, 1, &fileDesc); + AEDisposeDesc(&fileDesc); + } + +end: + if (dirName != NULL) { + Tcl_DStringFree(&ds); + } + return result; +} + +static void +InitFileDialogs() +{ + fileDlgInited = 1; + openFileFilterUPP = NewNavObjectFilterUPP(OpenFileFilterProc); + openFileEventUPP = NewNavEventUPP(OpenEventProc); +} + +static int +NavServicesGetFile( + Tcl_Interp *interp, + OpenFileData *ofdPtr, + AEDesc *initialDescPtr, + unsigned char *initialFile, + AEDescList *selectDescPtr, + StringPtr title, + StringPtr message, + int multiple, + int isOpen) +{ + NavReplyRecord theReply; + NavDialogCreationOptions diagOptions; + NavDialogRef dialogRef = NULL; + CFStringRef * menuItemNames = NULL; + OSErr err; + Tcl_Obj *theResult = NULL; + int result; + TextEncoding encoding; + + encoding = GetApplicationTextEncoding(); + err = NavGetDefaultDialogCreationOptions(&diagOptions); + if (err!=noErr) { + return TCL_ERROR; + } + diagOptions.location.h = -1; + diagOptions.location.v = -1; + diagOptions.optionFlags = kNavDontAutoTranslate + + kNavDontAddTranslateItems; + + if (multiple) { + diagOptions.optionFlags += kNavAllowMultipleFiles; + } + + if (ofdPtr != NULL && ofdPtr->usePopup) { + FileFilter *filterPtr; + + filterPtr = ofdPtr->fl.filters; + if (filterPtr == NULL) { + ofdPtr->usePopup = 0; + } + } + + if (ofdPtr != NULL && ofdPtr->usePopup) { + FileFilter *filterPtr; + int index = 0; + ofdPtr->curType = 0; + + menuItemNames = (CFStringRef *)ckalloc(ofdPtr->fl.numFilters + * sizeof(CFStringRef)); + + for (filterPtr = ofdPtr->fl.filters; filterPtr != NULL; + filterPtr = filterPtr->next, index++) { + menuItemNames[index] = CFStringCreateWithCString(NULL, + filterPtr->name, encoding); + } + diagOptions.popupExtension = CFArrayCreate(NULL, + (const void **)menuItemNames, ofdPtr->fl.numFilters, NULL);; + } else { + diagOptions.optionFlags += kNavNoTypePopup; + diagOptions.popupExtension = NULL; + } + + /* + * This is required to allow App packages to be selectable in the + * file dialogs... + */ + + diagOptions.optionFlags += kNavSupportPackages; + + diagOptions.clientName = CFStringCreateWithCString(NULL, "Wish", encoding); + if (message == NULL) { + diagOptions.message = NULL; + } else { + diagOptions.message = CFStringCreateWithPascalString(NULL, message, encoding); + } + if ((initialFile != NULL) && (initialFile[0] != 0)) { + diagOptions.saveFileName = CFStringCreateWithPascalString(NULL, + initialFile, encoding); + } else { + diagOptions.saveFileName = NULL; + } + if (title == NULL) { + diagOptions.windowTitle = NULL; + } else { + diagOptions.windowTitle = CFStringCreateWithPascalString(NULL, title, encoding); + } + + 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){ + fprintf(stderr,"NavCreateGetFileDialog failed, %d\n", err ); + dialogRef = NULL; + } + } else if (isOpen == SAVE_FILE) { + err = NavCreatePutFileDialog(&diagOptions, 'TEXT', 'WIsH', + openFileEventUPP, NULL, &dialogRef); + if (err!=noErr){ + fprintf(stderr,"NavCreatePutFileDialog failed, %d\n", err ); + dialogRef = NULL; + } + } else if (isOpen == CHOOSE_FOLDER) { + err = NavCreateChooseFolderDialog(&diagOptions, openFileEventUPP, + openFileFilterUPP, NULL, &dialogRef); + if (err!=noErr){ + fprintf(stderr,"NavCreateChooseFolderDialog failed, %d\n", err ); + dialogRef = NULL; + } + } + + if (dialogRef) { + if (initialDescPtr != NULL) { + NavCustomControl (dialogRef, kNavCtlSetLocation, initialDescPtr); + } + if ((selectDescPtr != NULL) + && (selectDescPtr->descriptorType != typeNull)) { + NavCustomControl(dialogRef, kNavCtlSetSelection, &selectDescPtr); + } + + if ((err = NavDialogRun(dialogRef)) != noErr ){ + fprintf(stderr,"NavDialogRun failed, %d\n", err ); + } else { + if ((err = NavDialogGetReply(dialogRef, &theReply)) != noErr) { + fprintf(stderr,"NavGetReply failed, %d\n", err ); + } + } + } + + /* + * Most commands assume that the file dialogs return a single + * item, not a list. So only build a list if multiple is true... + */ + if (err==noErr) { + if (multiple) { + theResult = Tcl_NewListObj(0, NULL); + } else { + theResult = Tcl_NewObj(); + } + if (!theResult) { + err = memFullErr; + } + } + if (theReply.validRecord && err==noErr) { + AEDesc resultDesc; + long count; + Tcl_DString fileName; + FSRef fsRef; + char pathPtr[1024]; + int pathValid = 0; + err = AECountItems(&theReply.selection, &count); + if (err == noErr) { + long i; + for (i = 1; i <= count; i++ ) { + err = AEGetNthDesc(&theReply.selection, + i, typeFSRef, NULL, &resultDesc); + pathValid = 0; + if (err == noErr) { + if ((err = AEGetDescData(&resultDesc, &fsRef, sizeof(fsRef))) + != noErr ) { + fprintf(stderr,"AEGetDescData failed %d\n", err ); + } else { + if (err = FSRefMakePath(&fsRef, pathPtr, 1024) ) { + fprintf(stderr,"FSRefMakePath failed, %d\n", err ); + } else { + if (isOpen == SAVE_FILE) { + CFStringRef saveNameRef; + char saveName [1024]; + if (saveNameRef = NavDialogGetSaveFileName(dialogRef)) { + if (CFStringGetCString(saveNameRef, saveName, + 1024, encoding)) { + strcat(pathPtr, "/"); + strcat(pathPtr, saveName); + pathValid = 1; + } else { + fprintf(stderr, "CFStringGetCString failed\n"); + } + } else { + fprintf(stderr, "NavDialogGetSaveFileName failed\n"); + } + } else { + pathValid = 1; + } + if (pathValid) { + /* + * Tested this and NULL=utf-8 encoding is + * good here + */ + Tcl_ExternalToUtfDString(NULL, pathPtr, -1, + &fileName); + if (multiple) { + Tcl_ListObjAppendElement(interp, theResult, + Tcl_NewStringObj(Tcl_DStringValue(&fileName), + Tcl_DStringLength(&fileName))); + } else { + Tcl_SetStringObj(theResult, Tcl_DStringValue(&fileName), + Tcl_DStringLength(&fileName)); + } + Tcl_DStringFree(&fileName); + } + } + } + AEDisposeDesc(&resultDesc); + } + } + } + err = NavDisposeReply(&theReply); + 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 + */ + + if (diagOptions.windowTitle) { + CFRelease(diagOptions.windowTitle); + } + if (diagOptions.saveFileName) { + CFRelease(diagOptions.saveFileName); + } + if (diagOptions.message) { + CFRelease(diagOptions.message); + } + if (diagOptions.clientName) { + CFRelease(diagOptions.clientName); + } + /* + * dispose of the CFArray diagOptions.popupExtension + */ + + if (menuItemNames) { + int i; + for (i=0;i < ofdPtr->fl.numFilters;i++) { + CFRelease(menuItemNames[i]); + } + ckfree((void *)menuItemNames); + } + if (diagOptions.popupExtension != NULL) { + CFRelease(diagOptions.popupExtension); + } + + return result; +} + +static pascal Boolean +OpenFileFilterProc( + AEDesc* theItem, void* info, + NavCallBackUserData callBackUD, + NavFilterModes filterMode ) +{ + OpenFileData *ofdPtr = (OpenFileData *) callBackUD; + if (!ofdPtr || !ofdPtr->usePopup) { + return true; + } else { + if (ofdPtr->fl.numFilters == 0) { + return true; + } else { + + if ( theItem->descriptorType == typeFSS ) { + NavFileOrFolderInfo* theInfo = (NavFileOrFolderInfo*)info; + int result; + + if ( !theInfo->isFolder ) { + OSType fileType; + StringPtr fileNamePtr; + int i; + FileFilter *filterPtr; + + fileType = theInfo->fileAndFolder.fileInfo.finderInfo.fdType; + HLock((Handle)theItem->dataHandle); + fileNamePtr = (((FSSpec *) *theItem->dataHandle)->name); + + if (ofdPtr->usePopup) { + i = ofdPtr->curType; + for (filterPtr = ofdPtr->fl.filters; filterPtr && i > 0; i--) { + filterPtr = filterPtr->next; + } + if (filterPtr) { + result = MatchOneType(fileNamePtr, fileType, + ofdPtr, filterPtr); + } else { + result = false; + } + } else { + /* + * We are not using the popup menu. In this case, the file is + * considered matched if it matches any of the file filters. + */ + result = UNMATCHED; + for (filterPtr = ofdPtr->fl.filters; filterPtr; + filterPtr = filterPtr->next) { + if (MatchOneType(fileNamePtr, fileType, + ofdPtr, filterPtr) == MATCHED) { + result = MATCHED; + break; + } + } + } + + HUnlock((Handle)theItem->dataHandle); + 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 */ + } + } +} + +/* + *---------------------------------------------------------------------- + * + * MatchOneType -- + * + * 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. + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +static Boolean +MatchOneType( + StringPtr fileNamePtr, /* Name of the file */ + OSType fileType, /* Type of the file */ + OpenFileData * ofdPtr, /* Information about this file dialog */ + FileFilter * filterPtr) /* Match the file described by pb against + * this filter */ +{ + FileFilterClause * clausePtr; + + /* + * A file matches with a file type if it matches with at least one + * clause of the type. + * + * If the clause has both glob patterns and ostypes, the file must + * match with at least one pattern AND at least one ostype. + * + * If the clause has glob patterns only, the file must match with at least + * one pattern. + * + * If the clause has mac types only, the file must match with at least + * one mac type. + * + * If the clause has neither glob patterns nor mac types, it's + * considered an error. + */ + + for (clausePtr=filterPtr->clauses; clausePtr; clausePtr=clausePtr->next) { + int macMatched = 0; + int globMatched = 0; + GlobPattern * globPtr; + MacFileType * mfPtr; + + if (clausePtr->patterns == NULL) { + globMatched = 1; + } + if (clausePtr->macTypes == NULL) { + macMatched = 1; + } + + for (globPtr=clausePtr->patterns; globPtr; globPtr=globPtr->next) { + char filename[256]; + int len; + char * p, *q, *ext; + + if (fileNamePtr == NULL) { + continue; + } + p = (char*)(fileNamePtr); + len = p[0]; + strncpy(filename, p+1, len); + filename[len] = '\0'; + ext = globPtr->pattern; + + if (ext[0] == '\0') { + /* + * We don't want any extensions: OK if the filename doesn't + * have "." in it + */ + for (q=filename; *q; q++) { + if (*q == '.') { + goto glob_unmatched; + } + } + goto glob_matched; + } + + if (Tcl_StringMatch(filename, ext)) { + goto glob_matched; + } else { + goto glob_unmatched; + } + + glob_unmatched: + continue; + + glob_matched: + globMatched = 1; + break; + } + + for (mfPtr=clausePtr->macTypes; mfPtr; mfPtr=mfPtr->next) { + if (fileType == mfPtr->type) { + macMatched = 1; + break; + } + } + + if (globMatched && macMatched) { + return MATCHED; + } + } + + return UNMATCHED; +} + +/* + *---------------------------------------------------------------------- + * + * TkAboutDlg -- + * + * Displays the default Tk About box. This code uses Macintosh + * resources to define the content of the About Box. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkAboutDlg() +{ + DialogPtr aboutDlog; + WindowRef windowRef; + short itemHit = -9; + + aboutDlog = GetNewDialog(128, NULL, (void *) (-1)); + + if (!aboutDlog) { + return; + } + + windowRef=GetDialogWindow(aboutDlog); + SelectWindow(windowRef); + + while (itemHit != 1) { + ModalDialog( NULL, &itemHit); + } + DisposeDialog(aboutDlog); + aboutDlog = NULL; + + SelectWindow(FrontNonFloatingWindow()); + + return; +} diff --git a/macosx/tkMacOSXDraw.c b/macosx/tkMacOSXDraw.c new file mode 100644 index 0000000..3edcfe9 --- /dev/null +++ b/macosx/tkMacOSXDraw.c @@ -0,0 +1,1714 @@ +/* + * tkMacOSXDraw.c -- + * + * 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. + * + * 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.2 2002/08/31 06:12:29 das Exp $ + */ + +#include "tkInt.h" +#include "X11/X.h" +#include "X11/Xlib.h" +#include <stdio.h> + +#include <Carbon/Carbon.h> +#include "tkMacOSXInt.h" +#include "tkPort.h" +#include "tkMacOSXDebug.h" + +#ifndef PI +# define PI 3.14159265358979323846 +#endif +#define RGBFLOATRED( c ) (float)((float)(c.red) / 65535.0) +#define RGBFLOATGREEN( c ) (float)((float)(c.green) / 65535.0) +#define RGBFLOATBLUE( c ) (float)((float)(c.blue) / 65535.0) + +/* + * Temporary regions that can be reused. + */ + +static RgnHandle tmpRgn = NULL; +static RgnHandle tmpRgn2 = NULL; + +static PixPatHandle gPenPat = NULL; + +static int useCGDrawing = 0; + +/* + * Prototypes for functions used only in this file. + */ +static unsigned char InvertByte _ANSI_ARGS_((unsigned char data)); + +void TkMacOSXSetUpCGContext(MacDrawable *macWin, + CGrafPtr destPort, GC gc, CGContextRef *contextPtr); +void TkMacOSXReleaseCGContext(MacDrawable *macWin, CGrafPtr destPort, + CGContextRef *context); +/* + *---------------------------------------------------------------------- + * + * XCopyArea -- + * + * Copies data from one drawable to another using block transfer + * routines. + * + * Results: + * None. + * + * Side effects: + * 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. */ + unsigned int height, + 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; + short tmode; + RGBColor origForeColor, origBackColor, whiteColor, blackColor; + Rect clpRect; + + dstPort = TkMacOSXGetDrawablePort(dst); + srcPort = TkMacOSXGetDrawablePort(src); + + display->request++; + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(dstPort, NULL); + GetForeColor(&origForeColor); + GetBackColor(&origBackColor); + whiteColor.red = 0; + whiteColor.blue = 0; + whiteColor.green = 0; + RGBForeColor(&whiteColor); + blackColor.red = 0xFFFF; + blackColor.blue = 0xFFFF; + blackColor.green = 0xFFFF; + RGBBackColor(&blackColor); + + if (tmpRgn2 == NULL) { + tmpRgn2 = NewRgn(); + } + srcPtr = &srcRect; + SetRect(&srcRect, (short) (srcDraw->xOff + src_x), + (short) (srcDraw->yOff + src_y), + (short) (srcDraw->xOff + src_x + width ), + (short) (srcDraw->yOff + src_y + height)); + if (tkPictureIsOpen ) { + dstPtr = &srcRect; + } else { + dstPtr = &dstRect; + SetRect(&dstRect, (short) (dstDraw->xOff + dest_x), + (short) (dstDraw->yOff + dest_y), + (short) (dstDraw->xOff + dest_x + width ), + (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. + */ + + GetClip(tmpRgn2); + 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 + * In this case, would have also clipped to the srcRect + * ClipRect(&srcRect); + */ + GetPortBounds(dstPort,&clpRect); + dstPtr = &srcRect; + ClipRect(&clpRect); + } + if (!gc->clip_mask ) { + } else if (((TkpClipMask*)gc->clip_mask)->type == TKP_CLIP_REGION) { + RgnHandle clipRgn = (RgnHandle) + ((TkpClipMask*)gc->clip_mask)->value.region; + + int xOffset, yOffset; + 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); + if (!tkPictureIsOpen) { + OffsetRgn(clipRgn, -xOffset, -yOffset); + } + } + srcBit = GetPortBitMapForCopyBits( srcPort ); + dstBit = GetPortBitMapForCopyBits( dstPort ); + tmode = srcCopy; + + CopyBits(srcBit, dstBit, srcPtr, dstPtr, tmode, NULL); + RGBForeColor(&origForeColor); + RGBBackColor(&origBackColor); + SetClip(tmpRgn2); + SetGWorld(saveWorld, saveDevice); +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * Results: + * None. + * + * Side effects: + * 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. */ +{ + 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; + TkpClipMask *clipPtr = (TkpClipMask*)gc->clip_mask; + short tmode; + + srcPort = TkMacOSXGetDrawablePort(src); + dstPort = TkMacOSXGetDrawablePort(dst); + + if (tmpRgn == NULL) { + tmpRgn = NewRgn(); + } + display->request++; + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(dstPort, NULL); + + TkMacOSXSetUpClippingRgn(dst); + + + srcBit = GetPortBitMapForCopyBits ( srcPort ); + dstBit = GetPortBitMapForCopyBits ( dstPort ); + SetRect(&srcRect, (short) (srcDraw->xOff + src_x), + (short) (srcDraw->yOff + src_y), + (short) (srcDraw->xOff + src_x + width), + (short) (srcDraw->yOff + src_y + height)); + srcPtr = &srcRect; + if (tkPictureIsOpen) { + /* + * 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 + */ + Rect clpRect; + GetPortBounds(dstPort,&clpRect); + ClipRect(&clpRect); + dstPtr = &srcRect; + } else { + dstPtr = &dstRect; + SetRect(&dstRect, (short) (dstDraw->xOff + dest_x), + (short) (dstDraw->yOff + dest_y), + (short) (dstDraw->xOff + dest_x + width), + (short) (dstDraw->yOff + dest_y + height)); + } + tmode = srcOr; + tmode = srcCopy + transparent; + + if (TkSetMacColor(gc->foreground, &macColor) == true) { + RGBForeColor(&macColor); + } + + if (clipPtr == NULL || clipPtr->type == TKP_CLIP_REGION) { + + /* + * Case 1: opaque bitmaps. + */ + TkSetMacColor(gc->background, &macColor); + RGBBackColor(&macColor); + 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 + * the forecolor. + */ + pm=GetPortPixMap(srcPort); + if (GetPixDepth(pm)== 1) { + tmode = srcOr; + } else { + tmode = transparent; + } + CopyBits(srcBit, dstBit, srcPtr, dstPtr, tmode, NULL); + } else { + /* + * Case 3: two arbitrary bitmaps. + */ + tmode = srcCopy; + mskPort = TkMacOSXGetDrawablePort(clipPtr->value.pixmap); + mskBit = GetPortBitMapForCopyBits ( mskPort ); + CopyDeepMask(srcBit, mskBit, dstBit, + srcPtr, srcPtr, dstPtr, tmode, NULL); + } + } + + SetGWorld(saveWorld, saveDevice); +} + +/* + *---------------------------------------------------------------------- + * + * TkPutImage -- + * + * Copies a subimage from an in-memory image to a rectangle of + * of the specified drawable. + * + * Results: + * None. + * + * Side effects: + * Draws the image on the specified drawable. + * + *---------------------------------------------------------------------- + */ + +void +TkPutImage( + unsigned long *colors, /* Unused on Macintosh. */ + int ncolors, /* Unused on Macintosh. */ + Display* display, /* Display. */ + Drawable d, /* Drawable to place image on. */ + GC gc, /* GC to use. */ + XImage* image, /* Image to place. */ + int src_x, /* Source X & Y. */ + int src_y, + int dest_x, /* Destination X & Y. */ + int dest_y, + unsigned int width, /* Same width & height for both */ + unsigned int height) /* distination and source. */ +{ + CGrafPtr saveWorld; + GDHandle saveDevice; + GWorldPtr destPort; + const BitMap * destBits; + int i, j; + BitMap bitmap; + char *newData = NULL; + Rect destRect, srcRect; + + destPort = TkMacOSXGetDrawablePort(d); + SetRect(&destRect, dest_x, dest_y, dest_x + width, dest_y + height); + SetRect(&srcRect, src_x, src_y, src_x + width, src_y + height); + + display->request++; + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + + TkMacOSXSetUpClippingRgn(d); + + if (image->depth == 1) { + + /* + * This code assumes a pixel depth of 1 + */ + + bitmap.bounds.top = bitmap.bounds.left = 0; + bitmap.bounds.right = (short) image->width; + bitmap.bounds.bottom = (short) image->height; + if ((image->bytes_per_line % 2) == 1) { + char *newPtr, *oldPtr; + newData = (char *) ckalloc(image->height * + (image->bytes_per_line + 1)); + newPtr = newData; + oldPtr = image->data; + for (i = 0; i < image->height; i++) { + for (j = 0; j < image->bytes_per_line; j++) { + *newPtr = InvertByte((unsigned char) *oldPtr); + newPtr++, oldPtr++; + } + *newPtr = 0; + newPtr++; + } + bitmap.baseAddr = newData; + bitmap.rowBytes = image->bytes_per_line + 1; + } else { + newData = (char *) ckalloc(image->height * image->bytes_per_line); + for (i = 0; i < image->height * image->bytes_per_line; i++) { + newData[i] = InvertByte((unsigned char) image->data[i]); + } + bitmap.baseAddr = newData; + bitmap.rowBytes = image->bytes_per_line; + } + destBits = GetPortBitMapForCopyBits ( destPort ); + CopyBits(&bitmap, destBits, + &srcRect, &destRect, srcCopy, NULL); + + } else { + /* Color image */ + PixMap pixmap; + + pixmap.bounds.left = 0; + pixmap.bounds.top = 0; + pixmap.bounds.right = (short) image->width; + pixmap.bounds.bottom = (short) image->height; + pixmap.pixelType = RGBDirect; + pixmap.pmVersion = 4; /* 32bit clean */ + pixmap.packType = 0; + pixmap.packSize = 0; + pixmap.hRes = 0x00480000; + pixmap.vRes = 0x00480000; + pixmap.pixelSize = 32; + pixmap.cmpCount = 3; + pixmap.cmpSize = 8; + pixmap.pixelFormat = 0; + pixmap.pmTable = NULL; + pixmap.pmExt = 0; + pixmap.baseAddr = image->data; + pixmap.rowBytes = image->bytes_per_line | 0x8000; + + CopyBits((BitMap *) &pixmap, GetPortBitMapForCopyBits ( destPort ), + &srcRect, &destRect, srcCopy, NULL); + } + + if (newData != NULL) { + ckfree(newData); + } + SetGWorld(saveWorld, saveDevice); +} + +/* + *---------------------------------------------------------------------- + * + * XFillRectangles -- + * + * Fill multiple rectangular areas in the given drawable. + * + * Results: + * None. + * + * Side effects: + * 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_rectangels) /* Number of rectangles. */ +{ + MacDrawable *macWin = (MacDrawable *) d; + CGrafPtr saveWorld; + GDHandle saveDevice; + GWorldPtr destPort; + Rect theRect; + int i; + + destPort = TkMacOSXGetDrawablePort(d); + + display->request++; + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + + TkMacOSXSetUpClippingRgn(d); + + TkMacOSXSetUpGraphicsPort(gc, destPort); + + for (i=0; i<n_rectangels; i++) { + theRect.left = (short) (macWin->xOff + rectangles[i].x); + theRect.top = (short) (macWin->yOff + rectangles[i].y); + theRect.right = (short) (theRect.left + rectangles[i].width); + theRect.bottom = (short) (theRect.top + rectangles[i].height); + FillCRect(&theRect, gPenPat); + } + + SetGWorld(saveWorld, saveDevice); +} + +/* + *---------------------------------------------------------------------- + * + * XDrawLines -- + * + * Draw connected lines. + * + * Results: + * None. + * + * Side effects: + * Renders a series of connected lines. + * + *---------------------------------------------------------------------- + */ + +void +XDrawLines( + Display* display, /* Display. */ + Drawable d, /* Draw on this. */ + GC gc, /* Use this GC. */ + 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; + int i; + + destPort = TkMacOSXGetDrawablePort(d); + + display->request++; + if (npoints < 2) { + return; /* TODO: generate BadValue error. */ + } + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + + TkMacOSXSetUpClippingRgn(d); + + if (useCGDrawing) { + CGContextRef outContext; + + TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); + + CGContextBeginPath(outContext); + CGContextMoveToPoint(outContext, (float) points[0].x, + (float) points[0].y); + if (mode == CoordModeOrigin) { + for (i = 1; i < npoints; i++) { + CGContextAddLineToPoint(outContext, + (float) points[i].x, + (float) points[i].y); + } + } + + CGContextStrokePath(outContext); + TkMacOSXReleaseCGContext(macWin, destPort, &outContext); + } else { + TkMacOSXSetUpGraphicsPort(gc, destPort); + + ShowPen(); + + PenPixPat(gPenPat); + MoveTo((short) (macWin->xOff + points[0].x), + (short) (macWin->yOff + points[0].y)); + for (i = 1; i < npoints; i++) { + if (mode == CoordModeOrigin) { + LineTo((short) (macWin->xOff + points[i].x), + (short) (macWin->yOff + points[i].y)); + } else { + Line((short) (macWin->xOff + points[i].x), + (short) (macWin->yOff + points[i].y)); + } + } + HidePen(); + + } + SetGWorld(saveWorld, saveDevice); +} + +/* + *---------------------------------------------------------------------- + * + * XDrawSegments -- + * + * Draw unconnected lines. + * + * Results: + * None. + * + * Side effects: + * Renders a series of connected lines. + * + *---------------------------------------------------------------------- + */ + +void XDrawSegments( + Display *display, + Drawable d, + GC gc, + XSegment *segments, + int nsegments) +{ + MacDrawable *macWin = (MacDrawable *) d; + CGrafPtr saveWorld; + GWorldPtr destPort; + GDHandle saveDevice; + int i; + + destPort = TkMacOSXGetDrawablePort(d); + + display->request++; + + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + + TkMacOSXSetUpClippingRgn(d); + + if (useCGDrawing) { + CGContextRef outContext; + + TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); + + CGContextBeginPath(outContext); + for (i = 0; i < nsegments; i++) { + CGContextMoveToPoint(outContext, + (float) segments[i].x1, + (float) segments[i].y1); + CGContextAddLineToPoint (outContext, + (float) segments[i].x2, + (float) segments[i].y2); + } + CGContextStrokePath(outContext); + TkMacOSXReleaseCGContext(macWin, destPort, &outContext); + } else { + TkMacOSXSetUpGraphicsPort(gc, destPort); + + ShowPen(); + + PenPixPat(gPenPat); + for (i = 0; i < nsegments; i++) { + MoveTo((short) (macWin->xOff + segments[i].x1), + (short) (macWin->yOff + segments[i].y1)); + LineTo((short) (macWin->xOff + segments[i].x2), + (short) (macWin->yOff + segments[i].y2)); + } + HidePen(); + } + + SetGWorld(saveWorld, saveDevice); +} + +/* + *---------------------------------------------------------------------- + * + * XFillPolygon -- + * + * Draws a filled polygon. + * + * Results: + * None. + * + * Side effects: + * Draws a filled polygon on the specified drawable. + * + *---------------------------------------------------------------------- + */ + +void +XFillPolygon( + Display* display, /* Display. */ + Drawable d, /* Draw on this. */ + GC gc, /* Use this GC. */ + XPoint* points, /* Array of points. */ + int npoints, /* Number of points. */ + int shape, /* Shape to draw. */ + int mode) /* Drawing mode. */ +{ + MacDrawable *macWin = (MacDrawable *) d; + PolyHandle polygon; + CGrafPtr saveWorld; + GDHandle saveDevice; + GWorldPtr destPort; + int i; + + destPort = TkMacOSXGetDrawablePort(d); + + display->request++; + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + + TkMacOSXSetUpClippingRgn(d); + + if (useCGDrawing) { + CGContextRef outContext; + + TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); + + CGContextBeginPath(outContext); + CGContextMoveToPoint(outContext, (float) (points[0].x), + (float) (points[0].y)); + for (i = 1; i < npoints; i++) { + + if (mode == CoordModePrevious) { + CGContextAddLineToPoint(outContext, (float) points[i].x, + (float) points[i].y); + } else { + } + } + //CGContextStrokePath(outContext); + CGContextFillPath(outContext); + TkMacOSXReleaseCGContext(macWin, destPort, &outContext); + } else { + TkMacOSXSetUpGraphicsPort(gc, destPort); + + PenNormal(); + polygon = OpenPoly(); + + MoveTo((short) (macWin->xOff + points[0].x), + (short) (macWin->yOff + points[0].y)); + for (i = 1; i < npoints; i++) { + if (mode == CoordModePrevious) { + Line((short) (macWin->xOff + points[i].x), + (short) (macWin->yOff + points[i].y)); + } else { + LineTo((short) (macWin->xOff + points[i].x), + (short) (macWin->yOff + points[i].y)); + } + } + + ClosePoly(); + + FillCPoly(polygon, gPenPat); + + KillPoly(polygon); + } + SetGWorld(saveWorld, saveDevice); +} + +/* + *---------------------------------------------------------------------- + * + * XDrawRectangle -- + * + * Draws a rectangle. + * + * Results: + * None. + * + * Side effects: + * 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. */ + unsigned int height) +{ + MacDrawable *macWin = (MacDrawable *) d; + Rect theRect; + CGrafPtr saveWorld; + GDHandle saveDevice; + GWorldPtr destPort; + + destPort = TkMacOSXGetDrawablePort(d); + + display->request++; + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + + TkMacOSXSetUpClippingRgn(d); + + TkMacOSXSetUpGraphicsPort(gc, destPort); + + theRect.left = (short) (macWin->xOff + x); + theRect.top = (short) (macWin->yOff + y); + theRect.right = (short) (theRect.left + width); + theRect.bottom = (short) (theRect.top + height); + + ShowPen(); + PenPixPat(gPenPat); + FrameRect(&theRect); + HidePen(); + + SetGWorld(saveWorld, saveDevice); +} + +/* + *---------------------------------------------------------------------- + * + * XDrawRectangles -- + * + * 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] + * + * 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. + * + * Side effects: + * Draws rectangles on the specified drawable. + * + *---------------------------------------------------------------------- + */ +void +XDrawRectangles( + Display *display, + Drawable drawable, + GC gc, + XRectangle *rectArr, + int nRects) +{ + MacDrawable *macWin = (MacDrawable *) drawable; + Rect rect; + CGrafPtr saveWorld; + GDHandle saveDevice; + GWorldPtr destPort; + XRectangle * rectPtr; + int i; + + destPort = TkMacOSXGetDrawablePort(drawable); + + display->request++; + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + + TkMacOSXSetUpClippingRgn(drawable); + + TkMacOSXSetUpGraphicsPort(gc, destPort); + + + ShowPen(); + PenPixPat(gPenPat); + + for (i = 0, rectPtr = rectArr; i < nRects;i++, rectPtr++ ) { + rect.left = (short) (macWin->xOff + rectPtr->x); + rect.top = (short) (macWin->yOff + rectPtr->y); + rect.right = (short) (rect.left + rectPtr->width); + rect.bottom = (short) (rect.top + rectPtr->height); + FrameRect(&rect); + } + HidePen(); + + SetGWorld(saveWorld, saveDevice); +} + +/* + *---------------------------------------------------------------------- + * + * XDrawArc -- + * + * Draw an arc. + * + * Results: + * None. + * + * Side effects: + * 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. */ + unsigned int height, + int angle1, /* Staring angle of arc. */ + int angle2) /* Ending angle of arc. */ +{ + MacDrawable *macWin = (MacDrawable *) d; + Rect theRect; + short start, extent; + CGrafPtr saveWorld; + GDHandle saveDevice; + GWorldPtr destPort; + float fX = (float) x, + fY = (float) y, + fWidth = (float) width, + fHeight = (float) height; + + if (width == 0 || height == 0) { + return; + } + + destPort = TkMacOSXGetDrawablePort(d); + + display->request++; + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + + TkMacOSXSetUpClippingRgn(d); + + if (useCGDrawing) { + CGContextRef outContext; + CGAffineTransform transform; + int clockwise = angle1 ? 0 : 1; + + TkMacOSXSetUpCGContext(macWin, destPort, gc, &outContext); + + CGContextBeginPath(outContext); + + /* + * If we are drawing an oval, we have to squash the coordinate + * system before drawing, since CGContextAddArcToPoint only draws + * circles. + */ + + CGContextSaveGState(outContext); + transform = CGAffineTransformMakeTranslation((float) (x + width/2), + (float) (y + height/2)); + transform = CGAffineTransformScale(transform, 1.0, fHeight/fWidth); + CGContextConcatCTM(outContext, transform); + + CGContextAddArc(outContext, 0.0, 0.0, + (float) width/2, + (float) angle1, (float) angle2, clockwise); + + CGContextRestoreGState(outContext); + + CGContextStrokePath(outContext); + TkMacOSXReleaseCGContext(macWin, destPort, &outContext); + } else { + TkMacOSXSetUpGraphicsPort(gc, destPort); + + + theRect.left = (short) (macWin->xOff + x); + theRect.top = (short) (macWin->yOff + y); + theRect.right = (short) (theRect.left + width); + theRect.bottom = (short) (theRect.top + height); + start = (short) (90 - (angle1 / 64)); + extent = (short) (-(angle2 / 64)); + + ShowPen(); + PenPixPat(gPenPat); + FrameArc(&theRect, start, extent); + HidePen(); + } + + SetGWorld(saveWorld, saveDevice); +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * Results: + * None. + * + * Side effects: + * Draws an arc for each array element on the specified drawable. + * + *---------------------------------------------------------------------- + */ +void +XDrawArcs( + Display *display, + Drawable d, + GC gc, + XArc *arcArr, + int nArcs) +{ + + MacDrawable *macWin = (MacDrawable *) d; + Rect rect; + short start, extent; + CGrafPtr saveWorld; + GDHandle saveDevice; + GWorldPtr destPort; + XArc * arcPtr; + int i; + + destPort = TkMacOSXGetDrawablePort(d); + + display->request++; + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + + TkMacOSXSetUpClippingRgn(d); + + TkMacOSXSetUpGraphicsPort(gc, destPort); + + + ShowPen(); + PenPixPat(gPenPat); + for (i = 0, arcPtr = arcArr;i < nArcs;i++, arcPtr++ ) { + rect.left = (short) (macWin->xOff + arcPtr->x); + rect.top = (short) (macWin->yOff + arcPtr->y); + rect.right = (short) (rect.left + arcPtr->width); + rect.bottom = (short) (rect.top + arcPtr->height); + start = (short) (90 - (arcPtr->angle1 / 64)); + extent = (short) (-(arcPtr->angle2 / 64)); + FrameArc(&rect, start, extent); + } + HidePen(); + + SetGWorld(saveWorld, saveDevice); +} + +/* + *---------------------------------------------------------------------- + * + * XFillArc -- + * + * Draw a filled arc. + * + * Results: + * None. + * + * Side effects: + * 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. */ + unsigned int height, + int angle1, /* Staring angle of arc. */ + int angle2) /* Ending angle of arc. */ +{ + MacDrawable *macWin = (MacDrawable *) d; + Rect theRect; + short start, extent; + PolyHandle polygon; + double sin1, cos1, sin2, cos2, angle; + double boxWidth, boxHeight; + double vertex[2], center1[2], center2[2]; + CGrafPtr saveWorld; + GDHandle saveDevice; + GWorldPtr destPort; + + destPort = TkMacOSXGetDrawablePort(d); + + display->request++; + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + + TkMacOSXSetUpClippingRgn(d); + + TkMacOSXSetUpGraphicsPort(gc, destPort); + + theRect.left = (short) (macWin->xOff + x); + theRect.top = (short) (macWin->yOff + y); + theRect.right = (short) (theRect.left + width); + theRect.bottom = (short) (theRect.top + height); + start = (short) (90 - (angle1 / 64)); + extent = (short) (- (angle2 / 64)); + + if (gc->arc_mode == ArcChord) { + boxWidth = theRect.right - theRect.left; + boxHeight = theRect.bottom - theRect.top; + angle = -(angle1/64.0)*PI/180.0; + sin1 = sin(angle); + cos1 = cos(angle); + angle -= (angle2/64.0)*PI/180.0; + sin2 = sin(angle); + cos2 = cos(angle); + vertex[0] = (theRect.left + theRect.right)/2.0; + vertex[1] = (theRect.top + theRect.bottom)/2.0; + center1[0] = vertex[0] + cos1*boxWidth/2.0; + center1[1] = vertex[1] + sin1*boxHeight/2.0; + center2[0] = vertex[0] + cos2*boxWidth/2.0; + center2[1] = vertex[1] + sin2*boxHeight/2.0; + + polygon = OpenPoly(); + MoveTo((short) ((theRect.left + theRect.right)/2), + (short) ((theRect.top + theRect.bottom)/2)); + + LineTo((short) (center1[0] + 0.5), (short) (center1[1] + 0.5)); + LineTo((short) (center2[0] + 0.5), (short) (center2[1] + 0.5)); + ClosePoly(); + + ShowPen(); + FillCArc(&theRect, start, extent, gPenPat); + FillCPoly(polygon, gPenPat); + HidePen(); + + KillPoly(polygon); + } else { + ShowPen(); + FillCArc(&theRect, start, extent, gPenPat); + HidePen(); + } + + SetGWorld(saveWorld, saveDevice); +} + +/* + *---------------------------------------------------------------------- + * + * XFillArcs -- + * + * Draw a filled arc. + * + * Results: + * None. + * + * Side effects: + * Draws a filled arc for each array element on the specified drawable. + * + *---------------------------------------------------------------------- + */ +void +XFillArcs( + Display *display, + Drawable d, + GC gc, + XArc *arcArr, + int nArcs) +{ + MacDrawable *macWin = (MacDrawable *) d; + Rect rect; + short start, extent; + PolyHandle polygon; + double sin1, cos1, sin2, cos2, angle; + double boxWidth, boxHeight; + double vertex[2], center1[2], center2[2]; + CGrafPtr saveWorld; + GDHandle saveDevice; + GWorldPtr destPort; + int i; + XArc * arcPtr; + + destPort = TkMacOSXGetDrawablePort(d); + + display->request++; + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + + TkMacOSXSetUpClippingRgn(d); + + TkMacOSXSetUpGraphicsPort(gc, destPort); + + for (i = 0, arcPtr = arcArr;i<nArcs;i++, arcPtr++ ) { + rect.left = (short) (macWin->xOff + arcPtr->x); + rect.top = (short) (macWin->yOff + arcPtr->y); + rect.right = (short) (rect.left + arcPtr->width); + rect.bottom = (short) (rect.top + arcPtr->height); + start = (short) (90 - (arcPtr->angle1 / 64)); + extent = (short) (- (arcPtr->angle2 / 64)); + + if (gc->arc_mode == ArcChord) { + boxWidth = rect.right - rect.left; + boxHeight = rect.bottom - rect.top; + angle = -(arcPtr->angle1/64.0)*PI/180.0; + sin1 = sin(angle); + cos1 = cos(angle); + angle -= (arcPtr->angle2/64.0)*PI/180.0; + sin2 = sin(angle); + cos2 = cos(angle); + vertex[0] = (rect.left + rect.right)/2.0; + vertex[1] = (rect.top + rect.bottom)/2.0; + center1[0] = vertex[0] + cos1*boxWidth/2.0; + center1[1] = vertex[1] + sin1*boxHeight/2.0; + center2[0] = vertex[0] + cos2*boxWidth/2.0; + center2[1] = vertex[1] + sin2*boxHeight/2.0; + + polygon = OpenPoly(); + MoveTo((short) ((rect.left + rect.right)/2), + (short) ((rect.top + rect.bottom)/2)); + + LineTo((short) (center1[0] + 0.5), (short) (center1[1] + 0.5)); + LineTo((short) (center2[0] + 0.5), (short) (center2[1] + 0.5)); + ClosePoly(); + + ShowPen(); + FillCArc(&rect, start, extent, gPenPat); + FillCPoly(polygon, gPenPat); + HidePen(); + + KillPoly(polygon); + } else { + ShowPen(); + FillCArc(&rect, start, extent, gPenPat); + HidePen(); + } + } + SetGWorld(saveWorld, saveDevice); +} + +/* + *---------------------------------------------------------------------- + * + * XMaxRequestSize -- + * + *---------------------------------------------------------------------- + */ +long +XMaxRequestSize(Display *display) +{ + return (SHRT_MAX / 4); +} + +/* + *---------------------------------------------------------------------- + * + * TkScrollWindow -- + * + * 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. + * + * Side effects: + * 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. */ +{ + MacDrawable *destDraw = (MacDrawable *) Tk_WindowId(tkwin); + RgnHandle rgn = (RgnHandle) damageRgn; + CGrafPtr saveWorld; + GDHandle saveDevice; + GWorldPtr destPort; + Rect srcRect, scrollRect; + RgnHandle visRgn, clipRgn; + + destPort = TkMacOSXGetDrawablePort(Tk_WindowId(tkwin)); + + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + + 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 + * 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 + * to "skip" over an area if the offset makes the source and + * destination rects disjoint and non-aligned. + */ + + SetRect(&srcRect, (short) (destDraw->xOff + x), + (short) (destDraw->yOff + y), + (short) (destDraw->xOff + x + width), + (short) (destDraw->yOff + y + height)); + scrollRect = srcRect; + if (dx < 0) { + scrollRect.left += dx; + } else { + scrollRect.right += dx; + } + if (dy < 0) { + scrollRect.top += dy; + } else { + scrollRect.bottom += dy; + } + + /* + * Adjust clip region so that we don't copy any windows + * that may overlap us. + */ + visRgn = NewRgn(); + clipRgn = NewRgn(); + RectRgn(rgn, &srcRect); + GetPortVisibleRegion(destPort,visRgn); + DiffRgn(rgn, visRgn, rgn); + OffsetRgn(rgn, dx, dy); + GetPortClipRegion(destPort, clipRgn); + DiffRgn(clipRgn, rgn, clipRgn); + SetPortClipRegion(destPort, clipRgn); + 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); + /* + * Fortunantly, the region returned by ScrollRect is symanticlly + * 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. + */ + if (EmptyRgn(rgn)) { + return 0; + } else { + return 1; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXSetUpGraphicsPort -- + * + * Set up the graphics port from the given GC. + * + * Results: + * None. + * + * Side effects: + * The current port is adjusted. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXSetUpGraphicsPort( + GC gc, + GWorldPtr destPort) /* GC to apply to current port. */ +{ + 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) { + unsigned char *p = (unsigned char *) &(gc->dashes); + /* + * 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, we either + * have to convert all line drawings to regions, or, on Mac OS X + * we can use CG to draw our lines instead of QuickDraw. + */ + } +} +/* + *---------------------------------------------------------------------- + * + * TkMacOSXSetUpGraphicsPort -- + * + * Set up the graphics port from the given GC. + * + * Results: + * None. + * + * Side effects: + * The current port is adjusted. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXSetUpCGContext( + MacDrawable *macWin, + CGrafPtr destPort, + GC gc, + CGContextRef *contextPtr) /* GC to apply to current port. */ +{ + RGBColor macColor; + CGContextRef outContext; + OSStatus err; + Rect boundsRect; + CGAffineTransform coordsTransform; + + err = QDBeginCGContext(destPort, contextPtr); + outContext = *contextPtr; + + CGContextSaveGState(outContext); + + GetPortBounds(destPort, &boundsRect); + + CGContextResetCTM(outContext); + coordsTransform = CGAffineTransformMake(1.0, 0.0, 0.0, -1.0, 0, + (float)(boundsRect.bottom - boundsRect.top)); + CGContextConcatCTM(outContext, coordsTransform); + + if (macWin->clipRgn != NULL) { + ClipCGContextToRegion(outContext, &boundsRect, macWin->clipRgn); + } else { + RgnHandle clipRgn = NewRgn(); + GetPortClipRegion(destPort, clipRgn); + ClipCGContextToRegion(outContext, &boundsRect, + clipRgn); + DisposeRgn(clipRgn); + } + + /* Now offset the CTM to the subwindow offset */ + + CGContextTranslateCTM(outContext, macWin->xOff, macWin->yOff); + + if (TkSetMacColor(gc->foreground, &macColor) == true) { + CGContextSetRGBStrokeColor(outContext, RGBFLOATRED(macColor), + RGBFLOATGREEN(macColor), + RGBFLOATBLUE(macColor), 1.0); + } + if (TkSetMacColor(gc->background, &macColor) == true) { + CGContextSetRGBFillColor(outContext, RGBFLOATRED(macColor), + RGBFLOATGREEN(macColor), + RGBFLOATBLUE(macColor), 1.0); + } + + if(gc->function == GXxor) { + } + + CGContextSetLineWidth(outContext, (float) gc->line_width); + + if (gc->line_style != LineSolid) { + unsigned char *p = (unsigned char *) &(gc->dashes); + /* + * 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, we either + * have to convert all line drawings to regions, or, on Mac OS X + * we can use CG to draw our lines instead of QuickDraw. + */ + } +} + +void +TkMacOSXReleaseCGContext( + MacDrawable *macWin, + CGrafPtr destPort, + CGContextRef *outContext) +{ + CGContextResetCTM(*outContext); + CGContextRestoreGState(*outContext); + QDEndCGContext(destPort, outContext); + +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXSetUpClippingRgn -- + * + * Set up the clipping region so that drawing only occurs on the + * specified X subwindow. + * + * Results: + * None. + * + * Side effects: + * The clipping region in the current port is changed. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXSetUpClippingRgn( + Drawable drawable) /* Drawable to update. */ +{ + MacDrawable *macDraw = (MacDrawable *) drawable; + + if (macDraw->winPtr != NULL) { + if (macDraw->flags & TK_CLIP_INVALID) { + TkMacOSXUpdateClipRgn(macDraw->winPtr); + } + + /* + * 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 (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); + } + } + } +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * Results: + * A BitMap data structure. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +BitMapPtr +TkMacOSXMakeStippleMap( + Drawable drawable, /* Window to apply stipple. */ + Drawable stipple) /* The stipple pattern. */ +{ + GWorldPtr destPort; + BitMapPtr bitmapPtr; + Rect portRect; + int width, height, stippleHeight, stippleWidth; + int i, j; + char * data; + Rect bounds; + + destPort = TkMacOSXGetDrawablePort(drawable); + + GetPortBounds ( destPort, &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; + + destPort = TkMacOSXGetDrawablePort(stipple); + stippleWidth = portRect.right - portRect.left; + stippleHeight = portRect.bottom - portRect.top; + + for (i = 0; i < height; i += stippleHeight) { + for (j = 0; j < width; j += stippleWidth) { + bounds.left = j; + bounds.top = i; + bounds.right = j + stippleWidth; + bounds.bottom = i + stippleHeight; + + CopyBits(GetPortBitMapForCopyBits ( destPort ), bitmapPtr, + &portRect, &bounds, srcCopy, NULL); + } + } + return bitmapPtr; +} + +/* + *---------------------------------------------------------------------- + * + * InvertByte -- + * + * This function reverses the bits in the passed in Byte of data. + * + * Results: + * The incoming byte in reverse bit order. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static unsigned char +InvertByte( + unsigned char data) /* Byte of data. */ +{ + unsigned char i; + unsigned char mask = 1, result = 0; + + for (i = (1 << 7); i != 0; i /= 2) { + if (data & mask) { + result |= i; + } + mask = mask << 1; + } + return result; +} + +/* + *---------------------------------------------------------------------- + * + * TkpDrawpHighlightBorder -- + * + * 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. + * + * For proper Mac L&F, use highlightWidth of 3. + * + * Results: + * None. + * + * Side effects: + * 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) +{ + if (highlightWidth == 1) { + TkDrawInsetFocusHighlight (tkwin, fgGC, highlightWidth, drawable, 0); + } else { + TkDrawInsetFocusHighlight (tkwin, bgGC, highlightWidth, drawable, 0); + if (fgGC != bgGC) { + TkDrawInsetFocusHighlight (tkwin, fgGC, highlightWidth - 1, drawable, 0); + } + } +} diff --git a/macosx/tkMacOSXEmbed.c b/macosx/tkMacOSXEmbed.c new file mode 100644 index 0000000..3405014 --- /dev/null +++ b/macosx/tkMacOSXEmbed.c @@ -0,0 +1,1193 @@ +/* + * 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. + * + * Copyright (c) 1996-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * 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.2 2002/08/31 06:12:29 das Exp $ + */ + +#include "tkInt.h" +#include "tkPort.h" +#include "X11/X.h" +#include "X11/Xlib.h" +#include <stdio.h> + +#include <Carbon/Carbon.h> +#include "tkMacOSXInt.h" + +/* + * One of the following structures exists for each container in this + * 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. */ +} Container; + +static Container *firstContainerPtr = NULL; + /* First in list of all containers + * managed by this process. */ +/* + * Globals defined in this file + */ + +TkMacOSXEmbedHandler *gMacEmbedHandler = 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)); + + +/* + *---------------------------------------------------------------------- + * + * 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 + * + * Results: + * None + * + * Side effects: + * The embed handler is set. + * + *---------------------------------------------------------------------- + */ +void +Tk_MacOSXSetEmbedHandler( + Tk_MacOSXEmbedRegisterWinProc *registerWinProc, + Tk_MacOSXEmbedGetGrafPortProc *getPortProc, + Tk_MacOSXEmbedMakeContainerExistProc *containerExistProc, + Tk_MacOSXEmbedGetClipProc *getClipProc, + Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc) +{ + if (gMacEmbedHandler == NULL) { + gMacEmbedHandler = (TkMacOSXEmbedHandler *) ckalloc(sizeof(TkMacOSXEmbedHandler)); + } + gMacEmbedHandler->registerWinProc = registerWinProc; + gMacEmbedHandler->getPortProc = getPortProc; + gMacEmbedHandler->containerExistProc = containerExistProc; + gMacEmbedHandler->getClipProc = getClipProc; + gMacEmbedHandler->getOffsetProc = getOffsetProc; +} + + +/* + *---------------------------------------------------------------------- + * + * TkpMakeWindow -- + * + * Creates an X Window (Mac subwindow). + * + * Results: + * The window id is returned. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Window +TkpMakeWindow( + TkWindow *winPtr, + Window parent) +{ + MacDrawable *macWin; + XEvent event; + + /* + * If this window is marked as embedded then + * the window structure should have already been + * created in the TkpUseWindow function. + */ + + if (Tk_IsEmbedded(winPtr)) { + return (Window) winPtr->privatePtr; + } + + /* + * Allocate sub window + */ + + macWin = (MacDrawable *) ckalloc(sizeof(MacDrawable)); + if (macWin == NULL) { + winPtr->privatePtr = NULL; + return None; + } + macWin->winPtr = winPtr; + winPtr->privatePtr = macWin; + macWin->clipRgn = NewRgn(); + macWin->aboveClipRgn = NewRgn(); + macWin->referenceCount = 0; + macWin->flags = TK_CLIP_INVALID; + + 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; + } 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->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; + Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); + + return (Window) macWin; +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * 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. + * + * Side effects: + * 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. */ +{ + TkWindow *winPtr = (TkWindow *) tkwin; + MacDrawable *parent, *macWin; + Container *containerPtr; + XEvent event; + int result; + + if (winPtr->window != None) { + panic("TkpUseWindow: X window already assigned"); + } + + /* + * 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 + * application as tkwin, since otherwise they would not be in our list + * of containers. + * + */ + + if (Tcl_GetInt(interp, string, &result) != TCL_OK) { + return TCL_ERROR; + } + + parent = (MacDrawable *) result; + + /* + * 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 + * 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; + } + } + + /* + * Make the embedded window. + */ + + macWin = (MacDrawable *) ckalloc(sizeof(MacDrawable)); + if (macWin == NULL) { + 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. + */ + + macWin->grafPtr = NULL; + + macWin->clipRgn = NewRgn(); + macWin->aboveClipRgn = 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 + * 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 (gMacEmbedHandler == NULL || + gMacEmbedHandler->registerWinProc(result, (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; + + } + } 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); + + } + + /* + * 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; +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkpMakeContainer( + Tk_Window tkwin) /* Token for a window that is about to + * become a container. */ +{ + TkWindow *winPtr = (TkWindow *) tkwin; + Container *containerPtr; + + /* + * Register the window as a container so that, for example, we can + * make sure the argument to -use is valid. + */ + + + Tk_MakeWindowExist(tkwin); + containerPtr = (Container *) ckalloc(sizeof(Container)); + containerPtr->parent = Tk_WindowId(tkwin); + containerPtr->parentPtr = winPtr; + containerPtr->embedded = None; + containerPtr->embeddedPtr = NULL; + 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 + * the container down to the embedded toplevel. + */ + + Tk_CreateEventHandler(tkwin, + SubstructureNotifyMask|SubstructureRedirectMask, + ContainerEventProc, (ClientData) winPtr); + Tk_CreateEventHandler(tkwin, StructureNotifyMask, EmbedStructureProc, + (ClientData) containerPtr); + Tk_CreateEventHandler(tkwin, ActivateMask, EmbedActivateProc, + (ClientData) containerPtr); + Tk_CreateEventHandler(tkwin, FocusChangeMask, EmbedFocusProc, + (ClientData) containerPtr); + +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXContainerId -- + * + * 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. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +MacDrawable * +TkMacOSXContainerId(winPtr) + 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; + } + } + panic("TkMacOSXContainerId couldn't find window"); + return None; +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXGetHostToplevel -- + * + * 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 + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +MacDrawable * +TkMacOSXGetHostToplevel( + TkWindow *winPtr) /* Tk's structure for a window. */ +{ + TkWindow *contWinPtr, *topWinPtr; + + topWinPtr = winPtr->privatePtr->toplevel->winPtr; + if (!Tk_IsEmbedded(topWinPtr)) { + 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; + } + } +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * Results: + * None. + * + * Side effects: + * 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. */ +{ + XEvent event; + Container *containerPtr; + + if (!(topLevelPtr->flags & TK_EMBEDDED)) { + return; + } + + for (containerPtr = firstContainerPtr; + containerPtr->embeddedPtr != topLevelPtr; + containerPtr = containerPtr->nextPtr) { + /* Empty loop body. */ + } + + + event.xfocus.type = FocusIn; + event.xfocus.serial = LastKnownRequestProcessed(topLevelPtr->display); + event.xfocus.send_event = 1; + event.xfocus.display = topLevelPtr->display; + event.xfocus.window = containerPtr->parent; + event.xfocus.mode = EMBEDDED_APP_WANTS_FOCUS; + event.xfocus.detail = force; + Tk_QueueWindowEvent(&event,TCL_QUEUE_TAIL); +} + +/* + *---------------------------------------------------------------------- + * + * TkpTestembedCmd -- + * + * 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. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkpTestembedCmd( + 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; + Tcl_DString dString; + char buffer[50]; + + if ((argc > 1) && (strcmp(argv[1], "all") == 0)) { + all = 1; + } else { + 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); + } + Tcl_DStringResult(interp, &dString); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * Results: + * None. + * + * Side effects: + * 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). */ +{ +} + +/* + *---------------------------------------------------------------------- + * + * TkpGetOtherWindow -- + * + * 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. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TkWindow * +TkpGetOtherWindow( + TkWindow *winPtr) /* Tk's structure for a container or + * embedded window. */ +{ + Container *containerPtr; + + /* + * TkpGetOtherWindow returns NULL if both windows are not + * in the same process... + */ + + if (!(winPtr->flags & TK_BOTH_HALVES)) { + 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; + } + } + 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. + * + * Results: + * None. + * + * Side effects: + * 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. */ +{ + TkWindow *winPtr = (TkWindow *) clientData; + + if (eventPtr->type == DestroyNotify) { + EmbedWindowDeleted(winPtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * NOTE: on the Mac, only the DestroyNotify branch is ever taken. + * We don't synthesize the other events. + * + * Results: + * None. + * + * Side effects: + * 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. */ +{ + TkWindow *winPtr = (TkWindow *) clientData; + Container *containerPtr; + Tk_ErrorHandler errHandler; + + /* + * Ignore any X protocol errors that happen in this procedure + * (almost any operation could fail, for example, if the embedded + * application has deleted its window). + */ + + errHandler = Tk_CreateErrorHandler(eventPtr->xfocus.display, -1, + -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) { + 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; + } 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); + } 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); + } else if (eventPtr->type == DestroyNotify) { + /* + * The embedded application is gone. Destroy the container window. + */ + + Tk_DestroyWindow((Tk_Window) winPtr); + } + Tk_DeleteErrorHandler(errHandler); +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * Results: + * None. + * + * Side effects: + * The embedded window gets resized to match the container. + * + *---------------------------------------------------------------------- + */ + +static void +EmbedStructureProc(clientData, eventPtr) + 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); + } + } else if (eventPtr->type == DestroyNotify) { + EmbedWindowDeleted(containerPtr->parentPtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * Results: + * None. + * + * Side effects: + * The X focus may change. + * + *---------------------------------------------------------------------- + */ + +static void +EmbedActivateProc(clientData, eventPtr) + 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); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * Results: + * None. + * + * Side effects: + * The X focus may change. + * + *---------------------------------------------------------------------- + */ + +static void +EmbedFocusProc(clientData, eventPtr) + ClientData clientData; /* Token for container window. */ + XEvent *eventPtr; /* ResizeRequest event. */ +{ + Container *containerPtr = (Container *) clientData; + Display *display; + XEvent event; + + 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; + + 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); + } +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * NOTE: On the Mac, this is a stub, since we don't synthesize + * ConfigureRequest events. + * + * Results: + * 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. + * + *---------------------------------------------------------------------- + */ + +static void +EmbedGeometryRequest(containerPtr, width, height) + 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 + * 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 + * chance to do whatever they want to do), and if the window's size + * didn't change then generate a configure event. + */ + + Tk_GeometryRequest((Tk_Window) winPtr, width, height); + while (Tcl_DoOneEvent(TCL_IDLE_EVENTS)) { + /* Empty loop body. */ + } + if ((winPtr->changes.width != width) + || (winPtr->changes.height != height)) { + EmbedSendConfigure(containerPtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * 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 + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +EmbedSendConfigure(containerPtr) + Container *containerPtr; /* Information about the embedding. */ +{ +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * Results: + * None. + * + * Side effects: + * A Container structure may be freed. + * + *---------------------------------------------------------------------- + */ + +static void +EmbedWindowDeleted(winPtr) + TkWindow *winPtr; /* Tk's information about window that + * was deleted. */ +{ + Container *containerPtr, *prevPtr; + + /* + * Find the Container structure for this window. Delete the + * information about the embedded application and free the container's + * record. + */ + + 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 == NULL) + && (containerPtr->parentPtr == NULL)) { + if (prevPtr == NULL) { + firstContainerPtr = containerPtr->nextPtr; + } else { + prevPtr->nextPtr = containerPtr->nextPtr; + } + ckfree((char *) containerPtr); + } +} + diff --git a/macosx/tkMacOSXEvent.c b/macosx/tkMacOSXEvent.c new file mode 100644 index 0000000..a55d0fd --- /dev/null +++ b/macosx/tkMacOSXEvent.c @@ -0,0 +1,276 @@ +/* + * tkMacOSXEvent.c -- + * + * This file contains most of the X calls called by Tk. Many of + * these calls are just stubs and either don't make sense on the + * Macintosh or thier implamentation just doesn't do anything. Other + * calls will eventually be moved into other files. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * 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.2 2002/08/31 06:12:29 das Exp $ + */ + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <pthread.h> +#include <sys/types.h> +#include <sys/ioctl.h> + +#include "tkMacOSXInt.h" +#include "tkMacOSXEvent.h" +#include "tkMacOSXDebug.h" + +#define TK_MAC_DEBUG 1 + +/* + * The following are undocumented event classes + * + */ +enum { + kEventClassUser = 'user', + kEventClassCgs = 'cgs ', +}; + +/* + * The following are undocumented event kinds + * + */ +enum { + kEventMouse8 = 8, + kEventMouse9 = 9, + kEventApp103 = 103 +}; + +EventRef TkMacOSXCreateFakeEvent (); + +/* + * Forward declarations of procedures used in this file. + */ +static int ReceiveAndProcessEvent _ANSI_ARGS_(()); + +static EventTargetRef targetRef; + +/* + *---------------------------------------------------------------------- + * + * tkMacOSXFlushWindows -- + * + * 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. + * + * Side effects: + * Flushes all Carbon windows + * + *---------------------------------------------------------------------- + */ + +void +tkMacOSXFlushWindows () +{ + WindowRef wRef = GetWindowList(); + + while (wRef) { + CGrafPtr portPtr = GetWindowPort(wRef); + if (QDIsPortBuffered(portPtr)) { + QDFlushPortBuffer(portPtr, NULL); + } + wRef=GetNextWindow(wRef); + } +} +/* + *---------------------------------------------------------------------- + * + * TkMacOSXCountAndProcessMacEvents -- + * + * This routine receives any Carbon events that aare in the + * queue and converts them to tk events + * It is called by the event set-up and check routines + * Results: + * The number of events in the queue. + * + * Side effects: + * Tells the Window Manager to deliver events to the event + * queue of the current thread. + * Receives any Carbon events on the queue and converts them to tk events + * + *---------------------------------------------------------------------- + */ + +int +TkMacOSXCountAndProcessMacEvents() +{ + EventQueueRef qPtr; + int eventCount; + qPtr = GetMainEventQueue(); + eventCount = GetNumEventsInQueue(qPtr); + if (eventCount) { + int n, err; + for (n = 0, err = 0;n<eventCount && !err;n++) { + err = ReceiveAndProcessEvent(); + } + } + return eventCount; +} +/* + *---------------------------------------------------------------------- + * + * TkMacOSXProcessAppleEvent -- + * + * This processes Apple events + * + * Results: + * 0 on success + * -1 on failure + * + * Side effects: + * Calls the Tk high-level event handler + * + *---------------------------------------------------------------------- + */ + +static int +TkMacOSXProcessAppleEvent(TkMacOSXEvent * eventPtr, MacEventStatus * statusPtr) +{ + int err; + EventRecord eventRecord; + if (ConvertEventRefToEventRecord(eventPtr->eventRef, + &eventRecord )) { + err=TkMacOSXDoHLEvent(&eventRecord); + if (err!=noErr) { + char buf1 [ 256 ]; + char buf2 [ 256 ]; + fprintf(stderr, + "TkMacOSXDoHLEvent failed : %s,%s,%d\n", + CarbonEventToAscii(eventPtr->eventRef, buf1), + ClassicEventToAscii(&eventRecord,buf2), err); + statusPtr->err = 1; + } else { + statusPtr->handledByTk = 1; + } + } else { + statusPtr->err = 1; + fprintf(stderr,"ConvertEventRefToEventRecord failed\n"); + } + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXProcessEvent -- + * + * This dispatches a filtered Carbon event to the appropriate handler + * + * Results: + * 0 on success + * -1 on failure + * + * Side effects: + * Converts a Carbon event to a Tk event + * + *---------------------------------------------------------------------- + */ + +static 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 kEventClassAppleEvent: + TkMacOSXProcessAppleEvent(eventPtr, statusPtr); + break; + case kEventClassCgs: + case kEventClassUser: + case kEventClassWish: + statusPtr->handledByTk = 1; + break; + default: +#ifdef TK_MAC_DEBUG + if (0) + { + char buf [ 256 ]; + fprintf(stderr, + "Unrecognised event : %s\n", + CarbonEventToAscii(eventPtr->eventRef, buf)); + } +#endif + break; + } + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * ReceiveAndProcessEvent -- + * + * 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 + * + *---------------------------------------------------------------------- + */ + +static int +ReceiveAndProcessEvent() +{ + TkMacOSXEvent macEvent; + MacEventStatus eventStatus; + int err; + char buf [ 256 ]; + + /* + * 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, &macEvent.eventRef); + if (err != noErr) { + return err; + } else { + macEvent.eClass = GetEventClass(macEvent.eventRef); + macEvent.eKind = GetEventKind(macEvent.eventRef); + bzero(&eventStatus, sizeof(eventStatus)); + TkMacOSXProcessEvent(&macEvent,&eventStatus); + if (!eventStatus.handledByTk) { + if (!targetRef) { + targetRef=GetEventDispatcherTarget(); + } + + err= SendEventToEventTarget(macEvent.eventRef,targetRef); + if (err != noErr /* && err != eventNotHandledErr */) { + fprintf(stderr, + "RCNE SendEventToEventTarget (%s) failed, %d\n", + CarbonEventToAscii(macEvent.eventRef,buf ),err); + } + } + ReleaseEvent(macEvent.eventRef); + return 0; + } +} diff --git a/macosx/tkMacOSXEvent.h b/macosx/tkMacOSXEvent.h new file mode 100644 index 0000000..2ce339b --- /dev/null +++ b/macosx/tkMacOSXEvent.h @@ -0,0 +1,86 @@ +/* + * tkMacOSXEvent.h -- + * + * Declarations of Macintosh specific functions for implementing the + * Mac OS X Notifier. + * + * Copyright 2001, Apple Computer, Inc. + * + * 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. + */ + +#ifndef _TKMACEVENT +#define _TKMACEVENT + +#include <Carbon/Carbon.h> +#include <tcl.h> + +enum { + kEventClassWish = 'WiSH' +}; + +typedef struct { + int handledByTk; + int err; + char errMsg[1024]; +} MacEventStatus; + +/* + * The event information in passed in the following structures + */ +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 */ +} TkMacOSXEvent; + +int TkMacOSXCountAndProcessMacEvents _ANSI_ARGS_(()); +void tkMacOSXFlushWindows _ANSI_ARGS_(()); +int TkMacOSXProcessMouseEvent(TkMacOSXEvent * e, MacEventStatus * statusPtr); +int TkMacOSXProcessWindowEvent(TkMacOSXEvent * e, MacEventStatus * statusPtr); +int TkMacOSXProcessKeyboardEvent(TkMacOSXEvent * e, MacEventStatus * statusPtr); +int TkMacOSXProcessApplicationEvent(TkMacOSXEvent * e, MacEventStatus * statusPtr); + +#endif diff --git a/macosx/tkMacOSXFont.c b/macosx/tkMacOSXFont.c new file mode 100644 index 0000000..40e637d --- /dev/null +++ b/macosx/tkMacOSXFont.c @@ -0,0 +1,2191 @@ +/* + * tkMacOSXFont.c -- + * + * Contains the Macintosh implementation of the platform-independant + * font package interface. + * + * Copyright (c) 1990-1994 The Regents of the University of California. + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkMacOSXFont.c,v 1.2 2002/08/31 06:12:29 das Exp $ + */ +#include <Carbon/Carbon.h> + +#include "tkMacOSXInt.h" +#include "tkFont.h" + +/* + * For doing things with Mac strings and Fixed numbers. This probably should move + * the mac header file. + */ + +#ifndef StrLength +#define StrLength(s) (*((unsigned char *) (s))) +#endif +#ifndef StrBody +#define StrBody(s) ((char *) (s) + 1) +#endif +#define pstrcmp(s1, s2) RelString((s1), (s2), 1, 1) +#define pstrcasecmp(s1, s2) RelString((s1), (s2), 0, 1) + +#ifndef Fixed2Int +#define Fixed2Int(f) ((f) >> 16) +#define Int2Fixed(i) ((i) << 16) +#endif + +/* + * The preferred font encodings. + */ + +static CONST char *encodingList[] = { + "macRoman", "macJapan", NULL +}; + +/* + * The following structures are used to map the script/language codes of a + * font to the name that should be passed to Tcl_GetTextEncoding() to obtain + * the encoding for that font. The set of numeric constants is fixed and + * defined by Apple. + */ + +static TkStateMap scriptMap[] = { + {smRoman, "macRoman"}, + {smJapanese, "macJapan"}, + {smTradChinese, "macChinese"}, + {smKorean, "macKorean"}, + {smArabic, "macArabic"}, + {smHebrew, "macHebrew"}, + {smGreek, "macGreek"}, + {smCyrillic, "macCyrillic"}, + {smRSymbol, "macRSymbol"}, + {smDevanagari, "macDevanagari"}, + {smGurmukhi, "macGurmukhi"}, + {smGujarati, "macGujarati"}, + {smOriya, "macOriya"}, + {smBengali, "macBengali"}, + {smTamil, "macTamil"}, + {smTelugu, "macTelugu"}, + {smKannada, "macKannada"}, + {smMalayalam, "macMalayalam"}, + {smSinhalese, "macSinhalese"}, + {smBurmese, "macBurmese"}, + {smKhmer, "macKhmer"}, + {smThai, "macThailand"}, + {smLaotian, "macLaos"}, + {smGeorgian, "macGeorgia"}, + {smArmenian, "macArmenia"}, + {smSimpChinese, "macSimpChinese"}, + {smTibetan, "macTIbet"}, + {smMongolian, "macMongolia"}, + {smGeez, "macEthiopia"}, + {smEastEurRoman, "macCentEuro"}, + {smVietnamese, "macVietnam"}, + {smExtArabic, "macSindhi"}, + {NULL, NULL} +}; + +static TkStateMap romanMap[] = { + {langCroatian, "macCroatian"}, + {langSlovenian, "macCroatian"}, + {langIcelandic, "macIceland"}, + {langRomanian, "macRomania"}, + {langTurkish, "macTurkish"}, + {langGreek, "macGreek"}, + {NULL, NULL} +}; + +static TkStateMap cyrillicMap[] = { + {langUkrainian, "macUkraine"}, + {langBulgarian, "macBulgaria"}, + {NULL, NULL} +}; + +/* + * The following structure represents a font family. It is assumed that + * all screen fonts constructed from the same "font family" share certain + * properties; all screen fonts with the same "font family" point to a + * shared instance of this structure. The most important shared property + * is the character existence metrics, used to determine if a screen font + * can display a given Unicode character. + * + * Under Macintosh, a "font family" is uniquely identified by its face number. + */ + + +#define FONTMAP_SHIFT 10 + +#define FONTMAP_PAGES (1 << (sizeof(Tcl_UniChar) * 8 - FONTMAP_SHIFT)) +#define FONTMAP_BITSPERPAGE (1 << FONTMAP_SHIFT) + +typedef struct FontFamily { + struct FontFamily *nextPtr; /* Next in list of all known font families. */ + int refCount; /* How many SubFonts are referring to this + * FontFamily. When the refCount drops to + * zero, this FontFamily may be freed. */ + /* + * Key. + */ + + FMFontFamily faceNum; /* Unique face number key for this FontFamily. */ + + /* + * Derived properties. + */ + + Tcl_Encoding encoding; /* Encoding for this font family. */ + int isSymbolFont; /* Non-zero if this is a symbol family. */ + int isMultiByteFont; /* Non-zero if this is a multi-byte family. */ + char typeTable[256]; /* Table that identfies all lead bytes for a + * multi-byte family, used when measuring chars. + * If a byte is a lead byte, the value at the + * corresponding position in the typeTable is 1, + * otherwise 0. If this is a single-byte font, + * all entries are 0. */ + char *fontMap[FONTMAP_PAGES]; + /* Two-level sparse table used to determine + * quickly if the specified character exists. + * As characters are encountered, more pages + * in this table are dynamically added. The + * contents of each page is a bitmask + * consisting of FONTMAP_BITSPERPAGE bits, + * representing whether this font can be used + * to display the given character at the + * corresponding bit position. The high bits + * of the character are used to pick which + * page of the table is used. */ +} FontFamily; + +/* + * The following structure encapsulates an individual screen font. A font + * object is made up of however many SubFonts are necessary to display a + * stream of multilingual characters. + */ + +typedef struct SubFont { + char **fontMap; /* Pointer to font map from the FontFamily, + * cached here to save a dereference. */ + FontFamily *familyPtr; /* The FontFamily for this SubFont. */ +} SubFont; + +/* + * The following structure represents Macintosh's implementation of a font + * object. + */ + +#define SUBFONT_SPACE 3 + +typedef struct MacFont { + TkFont font; /* Stuff used by generic font package. Must + * be first in structure. */ + SubFont staticSubFonts[SUBFONT_SPACE]; + /* Builtin space for a limited number of + * SubFonts. */ + int numSubFonts; /* Length of following array. */ + SubFont *subFontArray; /* Array of SubFonts that have been loaded + * in order to draw/measure all the characters + * encountered by this font so far. All fonts + * start off with one SubFont initialized by + * AllocFont() from the original set of font + * attributes. Usually points to + * staticSubFonts, but may point to malloced + * space if there are lots of SubFonts. */ + + short size; /* Font size in pixels, constructed from + * font attributes. */ + short style; /* Style bits, constructed from font + * attributes. */ +} MacFont; + +/* + * The following structure is used to map between the UTF-8 name for a font and + * the name that the Macintosh uses to refer to the font, in order to determine + * if a font exists. The Macintosh names for fonts are stored in the encoding + * of the font itself. + */ + +typedef struct FontNameMap { + Tk_Uid utfName; /* The name of the font in UTF-8. */ + StringPtr nativeName; /* The name of the font in the font's encoding. */ + FMFontFamily faceNum; /* Unique face number for this font. */ +} FontNameMap; + +/* + * The list of font families that are currently loaded. As screen fonts + * are loaded, this list grows to hold information about what characters + * exist in each font family. + */ + +static FontFamily *fontFamilyList = NULL; + +/* + * Information cached about the system at startup time. + */ + +static FontNameMap *gFontNameMap = NULL; +static GWorldPtr gWorld = NULL; + +/* + * Procedures used only in this file. + */ + +static FontFamily * AllocFontFamily(CONST MacFont *fontPtr, int family); +static SubFont * CanUseFallback(MacFont *fontPtr, CONST char *fallbackName, int ch); +static SubFont * CanUseFallbackWithAliases(MacFont *fontPtr, CONST char *faceName, int ch, Tcl_DString *nameTriedPtr); +static SubFont * FindSubFontForChar(MacFont *fontPtr, int ch); +static void FontMapInsert(SubFont *subFontPtr, int ch); +static void FontMapLoadPage(SubFont *subFontPtr, int row); +static int FontMapLookup(SubFont *subFontPtr, int ch); +static void FreeFontFamily(FontFamily *familyPtr); +static void InitFont(Tk_Window tkwin, int family, int size, int style, MacFont *fontPtr); +static void InitSubFont(CONST MacFont *fontPtr, int family, SubFont *subFontPtr); +static void MultiFontDrawText(MacFont *fontPtr, CONST char *source, int numBytes, int x, int y); +static void ReleaseFont(MacFont *fontPtr); +static void ReleaseSubFont(SubFont *subFontPtr); +static int SeenName(CONST char *name, Tcl_DString *dsPtr); + +static CONST char * BreakLine(FontFamily *familyPtr, int flags, CONST char *source, int numBytes, int *widthPtr); +static int GetFamilyNum(CONST char *faceName, short *familyPtr); +static int GetFamilyOrAliasNum(CONST char *faceName, short *familyPtr); +static Tcl_Encoding GetFontEncoding(int faceNum, int allowSymbol, int *isSymbolPtr); +static Tk_Uid GetUtfFaceName(StringPtr faceNameStr); + + +/* + *------------------------------------------------------------------------- + * + * 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. + * + * Results: + * None. + * + * Side effects: + * See comments below. + * + *------------------------------------------------------------------------- + */ + +void +TkpFontPkgInit(mainPtr) + TkMainInfo *mainPtr; /* The application being created. */ +{ + FMFontFamilyIterator fontFamilyIterator; + FMFontFamily fontFamily; + FontNameMap *tmpFontNameMap, *newFontNameMap, *mapPtr; + int i, j, numFonts, fontMapOffset, isSymbol; + Str255 nativeName; + Tcl_DString ds; + Tcl_Encoding encoding; + Tcl_Encoding *encodings; + + if (gWorld == NULL) { + Rect rect = {0, 0, 1, 1}; + SetFractEnable(0); + /* + * Used for saving and restoring state while drawing and measuring. + */ + if (NewGWorld(&gWorld, 0, &rect, NULL, NULL, 0) != noErr) { + panic("TkpFontPkgInit: NewGWorld failed"); + } + /* + * The name of each font is stored in the encoding of that font. + * How would we translate a name from UTF-8 into the native encoding + * of the font unless we knew the encoding of that font? We can't. + * So, precompute the UTF-8 and native names of all fonts on the + * system. The when the user asks for font by its UTF-8 name, we + * lookup the name in that table and really ask for the font by its + * native name. Any unknown UTF-8 names will be mapped to the system + * font. + */ + FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &fontFamilyIterator); + numFonts = 0; + while (FMGetNextFontFamily(&fontFamilyIterator, &fontFamily) != kFMIterationCompleted) { + numFonts++; + } + tmpFontNameMap = (FontNameMap *) ckalloc(sizeof(FontNameMap) * numFonts); + encodings = (Tcl_Encoding *) ckalloc(sizeof(Tcl_Encoding) * numFonts); + mapPtr = tmpFontNameMap; + FMResetFontFamilyIterator(NULL, NULL, kFMDefaultOptions, &fontFamilyIterator); + i = 0; + while (FMGetNextFontFamily(&fontFamilyIterator, &fontFamily) != kFMIterationCompleted) { + mapPtr->faceNum = fontFamily; + encodings[i] = GetFontEncoding(mapPtr->faceNum, 0, &isSymbol); + FMGetFontFamilyName(fontFamily, nativeName ); + Tcl_ExternalToUtfDString(encodings[i], StrBody(nativeName), StrLength(nativeName), &ds); + mapPtr->utfName = Tk_GetUid(Tcl_DStringValue(&ds)); + mapPtr->nativeName = (StringPtr) ckalloc(StrLength(nativeName) + 1); + memcpy(mapPtr->nativeName, nativeName, StrLength(nativeName) + 1); + Tcl_DStringFree(&ds); + mapPtr++; + i++; + } + FMDisposeFontFamilyIterator (&fontFamilyIterator); + + /* + * Reorder FontNameMap so fonts with the preferred encodings are at + * the front of the list. The relative order of fonts that all have + * the same encoding is preserved. Fonts with unknown encodings get + * stuck at the end. + */ + newFontNameMap = (FontNameMap *) ckalloc(sizeof(FontNameMap) * (numFonts + 1)); + fontMapOffset = 0; + for (i = 0; encodingList[i] != NULL; i++) { + encoding = Tcl_GetEncoding(NULL, encodingList[i]); + if (encoding == NULL) { + continue; + } + for (j = 0; j < numFonts; j++) { + if (encodings[j] == encoding) { + newFontNameMap[fontMapOffset] = tmpFontNameMap[j]; + fontMapOffset++; + Tcl_FreeEncoding(encodings[j]); + tmpFontNameMap[j].utfName = NULL; + } + } + Tcl_FreeEncoding(encoding); + } + for (i = 0; i < numFonts; i++) { + if (tmpFontNameMap[i].utfName != NULL) { + newFontNameMap[fontMapOffset] = tmpFontNameMap[i]; + fontMapOffset++; + Tcl_FreeEncoding(encodings[i]); + } + } + if (fontMapOffset != numFonts) { + panic("TkpFontPkgInit: unexpected number of fonts"); + } + + mapPtr = &newFontNameMap[numFonts]; + mapPtr->utfName = NULL; + mapPtr->nativeName = NULL; + mapPtr->faceNum = 0; + + ckfree((char *) tmpFontNameMap); + ckfree((char *) encodings); + + gFontNameMap = newFontNameMap; + } +} + +/* + *--------------------------------------------------------------------------- + * + * TkpGetNativeFont -- + * + * 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. + * + * 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(). + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +TkFont * +TkpGetNativeFont( + Tk_Window tkwin, /* For display where font will be used. */ + CONST char *name) /* Platform-specific font name. */ +{ + SInt16 family; + MacFont *fontPtr; + + if (strcmp(name, "system") == 0) { + family = GetSysFont(); + } else if (strcmp(name, "application") == 0) { + family = GetAppFont(); + } else { + return NULL; + } + + fontPtr = (MacFont *) ckalloc(sizeof(MacFont)); + InitFont(tkwin, family, 0, 0, fontPtr); + + return (TkFont *) fontPtr; +} + +/* + *--------------------------------------------------------------------------- + * + * TkpGetFontFromAttributes -- + * + * 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. + * + * 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(). + * + * Side effects: + * 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. */ +{ + short faceNum, style; + int i, j; + CONST char *faceName, *fallback; + char ***fallbacks; + MacFont *fontPtr; + + /* + * Algorithm to get the closest font to the one requested. + * + * try fontname + * try all aliases for fontname + * foreach fallback for fontname + * try the fallback + * try all aliases for the fallback + */ + + faceNum = 0; + faceName = faPtr->family; + if (faceName != NULL) { + if (GetFamilyOrAliasNum(faceName, &faceNum) != 0) { + goto found; + } + fallbacks = TkFontGetFallbacks(); + for (i = 0; fallbacks[i] != NULL; i++) { + for (j = 0; (fallback = fallbacks[i][j]) != NULL; j++) { + if (strcasecmp(faceName, fallback) == 0) { + for (j = 0; (fallback = fallbacks[i][j]) != NULL; j++) { + if (GetFamilyOrAliasNum(fallback, &faceNum)) { + goto found; + } + } + } + break; + } + } + } + + found: + style = 0; + if (faPtr->weight != TK_FW_NORMAL) { + style |= bold; + } + if (faPtr->slant != TK_FS_ROMAN) { + style |= italic; + } + if (faPtr->underline) { + style |= underline; + } + if (tkFontPtr == NULL) { + fontPtr = (MacFont *) ckalloc(sizeof(MacFont)); + } else { + fontPtr = (MacFont *) tkFontPtr; + ReleaseFont(fontPtr); + } + InitFont(tkwin, faceNum, faPtr->size, style, fontPtr); + + return (TkFont *) fontPtr; +} + +/* + *--------------------------------------------------------------------------- + * + * 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. + * + * Results: + * None. + * + * Side effects: + * TkFont is deallocated. + * + *--------------------------------------------------------------------------- + */ + +void +TkpDeleteFont( + TkFont *tkFontPtr) /* Token of font to be deleted. */ +{ + MacFont *fontPtr; + + fontPtr = (MacFont *) tkFontPtr; + ReleaseFont(fontPtr); +} + +/* + *--------------------------------------------------------------------------- + * + * TkpGetFontFamilies -- + * + * 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. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +void +TkpGetFontFamilies( + Tcl_Interp *interp, /* Interp to hold result. */ + Tk_Window tkwin) /* For display to query. */ +{ + FontNameMap *mapPtr; + Tcl_Obj *resultPtr, *strPtr; + + resultPtr = Tcl_GetObjResult(interp); + for (mapPtr = gFontNameMap; mapPtr->utfName != NULL; mapPtr++) { + strPtr = Tcl_NewStringObj(mapPtr->utfName, -1); + Tcl_ListObjAppendElement(NULL, resultPtr, strPtr); + } +} + +/* + *------------------------------------------------------------------------- + * + * TkpGetSubFonts -- + * + * 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. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ + +void +TkpGetSubFonts(interp, tkfont) + Tcl_Interp *interp; /* Interp to hold result. */ + Tk_Font tkfont; /* Font object to query. */ +{ + int i; + Tcl_Obj *resultPtr, *strPtr; + MacFont *fontPtr; + FontFamily *familyPtr; + Str255 nativeName; + + resultPtr = Tcl_GetObjResult(interp); + fontPtr = (MacFont *) tkfont; + for (i = 0; i < fontPtr->numSubFonts; i++) { + familyPtr = fontPtr->subFontArray[i].familyPtr; + GetFontName(familyPtr->faceNum, nativeName); + strPtr = Tcl_NewStringObj(GetUtfFaceName(nativeName), -1); + Tcl_ListObjAppendElement(NULL, resultPtr, strPtr); + } +} + +/* + *--------------------------------------------------------------------------- + * + * 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. + * + * 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. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +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. */ +{ + MacFont *fontPtr; + FontFamily *lastFamilyPtr; + CGrafPtr saveWorld; + GDHandle saveDevice; + int curX, curByte; + + /* + * According to "Inside Macintosh: Text", the Macintosh may + * automatically substitute + * ligatures or context-sensitive presentation forms when + * measuring/displaying text within a font run. We cannot safely + * measure individual characters and add up the widths w/o errors. + * However, if we convert a range of text from UTF-8 to, say, + * Shift-JIS, and get the offset into the Shift-JIS string as to + * where a word or line break would occur, then can we map that + * number back to UTF-8? + */ + + fontPtr = (MacFont *) tkfont; + + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(gWorld, NULL); + + TextSize(fontPtr->size); + TextFace(fontPtr->style); + + lastFamilyPtr = fontPtr->subFontArray[0].familyPtr; + + if (numBytes == 0) { + curX = 0; + curByte = 0; + } else if (maxLength < 0) { + CONST char *p, *end, *next; + Tcl_UniChar ch; + FontFamily *thisFamilyPtr; + Tcl_DString runString; + + /* + * A three step process: + * 1. Find a contiguous range of characters that can all be + * represented by a single screen font. + * 2. Convert those chars to the encoding of that font. + * 3. Measure converted chars. + */ + + curX = 0; + end = source + numBytes; + for (p = source; p < end; ) { + next = p + Tcl_UtfToUniChar(p, &ch); + thisFamilyPtr = FindSubFontForChar(fontPtr, ch)->familyPtr; + if (thisFamilyPtr != lastFamilyPtr) { + TextFont(lastFamilyPtr->faceNum); + Tcl_UtfToExternalDString(lastFamilyPtr->encoding, source, + p - source, &runString); + curX += TextWidth(Tcl_DStringValue(&runString), 0, + Tcl_DStringLength(&runString)); + Tcl_DStringFree(&runString); + lastFamilyPtr = thisFamilyPtr; + source = p; + } + p = next; + } + TextFont(lastFamilyPtr->faceNum); + Tcl_UtfToExternalDString(lastFamilyPtr->encoding, source, p - source, + &runString); + curX += TextWidth(Tcl_DStringValue(&runString), 0, + Tcl_DStringLength(&runString)); + Tcl_DStringFree(&runString); + curByte = numBytes; + } else { + CONST char *p, *end, *next, *sourceOrig; + int widthLeft; + FontFamily *thisFamilyPtr; + Tcl_UniChar ch; + CONST char *rest = NULL; + + /* + * How many chars will fit in the space allotted? + */ + + if (maxLength > 32767) { + maxLength = 32767; + } + + widthLeft = maxLength; + sourceOrig = source; + end = source + numBytes; + for (p = source; p < end; p = next) { + next = p + Tcl_UtfToUniChar(p, &ch); + thisFamilyPtr = FindSubFontForChar(fontPtr, ch)->familyPtr; + if (thisFamilyPtr != lastFamilyPtr) { + if (p > source) { + rest = BreakLine(lastFamilyPtr, flags, source, + p - source, &widthLeft); + flags &= ~TK_AT_LEAST_ONE; + if (rest != NULL) { + p = source; + break; + } + } + lastFamilyPtr = thisFamilyPtr; + source = p; + } + } + + if (p > source) { + rest = BreakLine(lastFamilyPtr, flags, source, p - source, + &widthLeft); + } + + if (rest == NULL) { + curByte = numBytes; + } else { + curByte = rest - sourceOrig; + } + curX = maxLength - widthLeft; + } + + SetGWorld(saveWorld, saveDevice); + + *lengthPtr = curX; + return curByte; +} + +/* + *--------------------------------------------------------------------------- + * + * BreakLine -- + * + * Determine where the given line of text should be broken so that it + * fits in the specified range. Before calling this function, the + * font values and graphics port must be set. + * + * Results: + * The return value is NULL if the specified range is larger that the + * space the text needs, and *widthLeftPtr is filled with how much + * space is left in the range after measuring the whole text buffer. + * Otherwise, the return value is a pointer into the text buffer that + * indicates where the line should be broken (up to, but not including + * that character), and *widthLeftPtr is filled with how much space is + * left in the range after measuring up to that character. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +static CONST char * +BreakLine( + FontFamily *familyPtr, /* FontFamily that describes the font values + * that are already selected into the graphics + * port. */ + 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. */ + 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 *widthLeftPtr) /* On input, specifies size of range into + * which characters from source buffer should + * be fit. On output, filled with how much + * space is left after fitting as many + * characters as possible into the range. + * Result may be negative if TK_AT_LEAST_ONE + * was specified in the flags argument. */ +{ + Fixed pixelWidth, widthLeft; + StyledLineBreakCode breakCode; + Tcl_DString runString; + long textOffset; + Boolean leadingEdge; + Point point; + int charOffset, thisCharWasDoubleByte; + char *p, *end, *typeTable; + + TextFont(familyPtr->faceNum); + Tcl_UtfToExternalDString(familyPtr->encoding, source, numBytes, + &runString); + pixelWidth = Int2Fixed(*widthLeftPtr) + 1; + if (flags & TK_WHOLE_WORDS) { + textOffset = (flags & TK_AT_LEAST_ONE); + widthLeft = pixelWidth; + breakCode = StyledLineBreak(Tcl_DStringValue(&runString), + Tcl_DStringLength(&runString), 0, Tcl_DStringLength(&runString), + 0, &widthLeft, &textOffset); + if (breakCode != smBreakOverflow) { + /* + * StyledLineBreak includes all the space characters at the end of + * line that we want to suppress. + */ + + textOffset = VisibleLength(Tcl_DStringValue(&runString), textOffset); + goto getoffset; + } + } else { + point.v = 1; + point.h = 1; + textOffset = PixelToChar(Tcl_DStringValue(&runString), + Tcl_DStringLength(&runString), 0, pixelWidth, &leadingEdge, + &widthLeft, smOnlyStyleRun, point, point); + if (Fixed2Int(widthLeft) < 0) { + goto getoffset; + } + } + *widthLeftPtr = Fixed2Int(widthLeft); + Tcl_DStringFree(&runString); + return NULL; + + /* + * The conversion routine that converts UTF-8 to the target encoding + * must map one UTF-8 character to exactly one encoding-specific + * character, so that the following algorithm works: + * + * 1. Get byte offset of where line should be broken. + * 2. Get char offset corresponding to that byte offset. + * 3. Map that char offset to byte offset in UTF-8 string. + */ + + getoffset: + thisCharWasDoubleByte = 0; + if (familyPtr->isMultiByteFont == 0) { + charOffset = textOffset; + } else { + charOffset = 0; + typeTable = familyPtr->typeTable; + + p = Tcl_DStringValue(&runString); + end = p + textOffset; + thisCharWasDoubleByte = typeTable[*((unsigned char *) p)]; + for ( ; p < end; p++) { + thisCharWasDoubleByte = typeTable[*((unsigned char *) p)]; + p += thisCharWasDoubleByte; + charOffset++; + } + } + + if ((flags & TK_WHOLE_WORDS) == 0) { + if ((flags & TK_PARTIAL_OK) && (leadingEdge != 0)) { + textOffset += thisCharWasDoubleByte; + textOffset++; + charOffset++; + } else if (((flags & TK_PARTIAL_OK) == 0) && (leadingEdge == 0)) { + textOffset -= thisCharWasDoubleByte; + textOffset--; + charOffset--; + } + } + if ((textOffset == 0) && (Tcl_DStringLength(&runString) > 0) + && (flags & TK_AT_LEAST_ONE)) { + p = Tcl_DStringValue(&runString); + textOffset += familyPtr->typeTable[*((unsigned char *) p)]; + textOffset++; + charOffset++; + } + *widthLeftPtr = Fixed2Int(pixelWidth) + - TextWidth(Tcl_DStringValue(&runString), 0, textOffset); + Tcl_DStringFree(&runString); + return Tcl_UtfAtIndex(source, charOffset); +} + +/* + *--------------------------------------------------------------------------- + * + * Tk_DrawChars -- + * + * Draw a string of characters on the screen. + * + * Results: + * None. + * + * Side effects: + * 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 + * string when drawing. */ +{ + MacFont *fontPtr; + MacDrawable *macWin; + RGBColor macColor, origColor; + GWorldPtr destPort; + CGrafPtr saveWorld; + GDHandle saveDevice; + short txFont, txFace, txSize; + BitMapPtr stippleMap; + Rect portRect; + + fontPtr = (MacFont *) tkfont; + macWin = (MacDrawable *) drawable; + + destPort = TkMacOSXGetDrawablePort(drawable); + GetPortBounds(destPort, &portRect); + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + + TkMacOSXSetUpClippingRgn(drawable); + TkMacOSXSetUpGraphicsPort(gc, destPort); + + txFont = GetPortTextFont(destPort); + txFace = GetPortTextFace(destPort); + txSize = GetPortTextSize(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) == true) { + RGBForeColor(&macColor); + } + GetQDGlobalsWhite(&white); + ShowPen(); + FillRect(&stippleMap->bounds, &white); + MultiFontDrawText(fontPtr, source, numBytes, 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) == true) { + RGBForeColor(&macColor); + } + ShowPen(); + MultiFontDrawText(fontPtr, source, numBytes, macWin->xOff + x, + macWin->yOff + y); + HidePen(); + } + + TextFont(txFont); + TextSize(txSize); + TextFace(txFace); + RGBForeColor(&origColor); + SetGWorld(saveWorld, saveDevice); +} + +/* + *------------------------------------------------------------------------- + * + * MultiFontDrawText -- + * + * Helper function for Tk_DrawChars. Draws characters, using the + * various screen fonts in fontPtr to draw multilingual characters. + * Note: No bidirectional support. + * + * Results: + * None. + * + * Side effects: + * Information gets drawn on the screen. + * Contents of fontPtr may be modified if more subfonts were loaded + * in order to draw all the multilingual characters in the given + * string. + * + *------------------------------------------------------------------------- + */ + +static void +MultiFontDrawText( + MacFont *fontPtr, /* Contains set of fonts to use when drawing + * following string. */ + CONST char *source, /* Potentially multilingual UTF-8 string. */ + int numBytes, /* Length of string in bytes. */ + int x, int y) /* Coordinates at which to place origin * + * of string when drawing. */ +{ + FontFamily *lastFamilyPtr, *thisFamilyPtr = NULL; + Tcl_DString runString; + CONST char *p, *end, *next; + Tcl_UniChar ch; + + TextSize(fontPtr->size); + TextFace(fontPtr->style); + + lastFamilyPtr = fontPtr->subFontArray[0].familyPtr; + + end = source + numBytes; + for (p = source; p < end; ) { + next = p + Tcl_UtfToUniChar(p, &ch); + thisFamilyPtr = FindSubFontForChar(fontPtr, ch)->familyPtr; + if (thisFamilyPtr != lastFamilyPtr) { + if (p > source) { + TextFont(lastFamilyPtr->faceNum); + Tcl_UtfToExternalDString(lastFamilyPtr->encoding, source, + p - source, &runString); + MoveTo((short) x, (short) y); + DrawText(Tcl_DStringValue(&runString), 0, + Tcl_DStringLength(&runString)); + x += TextWidth(Tcl_DStringValue(&runString), 0, + Tcl_DStringLength(&runString)); + Tcl_DStringFree(&runString); + source = p; + } + lastFamilyPtr = thisFamilyPtr; + } + p = next; + } + if (p > source) { + TextFont(thisFamilyPtr->faceNum); + Tcl_UtfToExternalDString(lastFamilyPtr->encoding, source, + p - source, &runString); + MoveTo((short) x, (short) y); + DrawText(Tcl_DStringValue(&runString), 0, + Tcl_DStringLength(&runString)); + Tcl_DStringFree(&runString); + } +} + +/* + *--------------------------------------------------------------------------- + * + * TkMacOSXIsCharacterMissing -- + * + * Given a tkFont and a character determines whether the character has + * a glyph defined in the font or not. Note that this is potentially + * not compatible with Mac OS 8 as it looks at the font handle + * structure directly. Looks into the character array of the font + * handle to determine whether the glyph is defined or not. + * + * Results: + * Returns a 1 if the character is missing, a 0 if it is not. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +int +TkMacOSXIsCharacterMissing( + Tk_Font tkfont, /* The font we are looking in. */ + unsigned int searchChar) /* The character we are looking for. */ +{ +/* + * For some reason, FMSwapFont always returns a NULL font handle under OS X + * Until we figure this one out, return 0; + */ +#ifdef MAC_OSX_TK + return 0; +#else + MacFont *fontPtr = (MacFont *) tkfont; + FMInput fm; + FontRec **fontRecHandle; + FMOutPtr fmOutPtr; + + + fm.family = fontPtr->subFontArray[0].familyPtr->faceNum; + fm.size = fontPtr->size; + fm.face = fontPtr->style; + fm.needBits = 0; + fm.device = 0; + fm.numer.h = fm.numer.v = fm.denom.h = fm.denom.v = 1; + + fmOutPtr=FMSwapFont(&fm); + fprintf(stderr,"fmOut %08x, handle %08x\n", (int)fmOutPtr, fmOutPtr->fontHandle); + +#if !defined(UNIVERSAL_INTERFACES_VERSION) || (UNIVERSAL_INTERFACES_VERSION < 0x0300) + fontRecHandle = (FontRec **) FMSwapFont(&fm)->fontResult; +#else + fontRecHandle = (FontRec **) FMSwapFont(&fm)->fontHandle; +#endif + return *(short *) ((long) &(*fontRecHandle)->owTLoc + + ((long)((*fontRecHandle)->owTLoc + searchChar + - (*fontRecHandle)->firstChar) * sizeof(short))) == -1; +#endif +} + +/* + *--------------------------------------------------------------------------- + * + * InitFont -- + * + * 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(). + * + * Results: + * Fills the MacFont structure. + * + * Side effects: + * Memory allocated. + * + *--------------------------------------------------------------------------- + */ + +static void +InitFont( + Tk_Window tkwin, /* For display where font will be used. */ + int faceNum, /* Macintosh font number. */ + int size, /* Point size for Macintosh font. */ + int style, /* Macintosh style bits. */ + MacFont *fontPtr) /* Filled with information constructed from + * the above arguments. */ +{ + Str255 nativeName; + FontInfo fi; + TkFontAttributes *faPtr; + TkFontMetrics *fmPtr; + CGrafPtr saveWorld; + GDHandle saveDevice; + short pixels; + + if (size == 0) { + size = -GetDefFontSize(); + } + pixels = (short) TkFontGetPixels(tkwin, size); + + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(gWorld, NULL); + TextFont(faceNum); + + + TextSize(pixels); + TextFace(style); + + GetFontInfo(&fi); + GetFontName(faceNum, nativeName); + fontPtr->font.fid = (Font) fontPtr; + + faPtr = &fontPtr->font.fa; + faPtr->family = GetUtfFaceName(nativeName); + faPtr->size = TkFontGetPoints(tkwin, size); + faPtr->weight = (style & bold) ? TK_FW_BOLD : TK_FW_NORMAL; + faPtr->slant = (style & italic) ? TK_FS_ITALIC : TK_FS_ROMAN; + faPtr->underline = ((style & underline) != 0); + faPtr->overstrike = 0; + + fmPtr = &fontPtr->font.fm; + fmPtr->ascent = fi.ascent; + fmPtr->descent = fi.descent; + fmPtr->maxWidth = fi.widMax; + fmPtr->fixed = (CharWidth('i') == CharWidth('w')); + + fontPtr->size = pixels; + fontPtr->style = (short) style; + + fontPtr->numSubFonts = 1; + fontPtr->subFontArray = fontPtr->staticSubFonts; + InitSubFont(fontPtr, faceNum, &fontPtr->subFontArray[0]); + + SetGWorld(saveWorld, saveDevice); +} + +/* + *------------------------------------------------------------------------- + * + * ReleaseFont -- + * + * 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. + * + * Side effects: + * Memory is freed. + * + *--------------------------------------------------------------------------- + */ + +static void +ReleaseFont( + MacFont *fontPtr) /* The font to delete. */ +{ + int i; + + for (i = 0; i < fontPtr->numSubFonts; i++) { + ReleaseSubFont(&fontPtr->subFontArray[i]); + } + if (fontPtr->subFontArray != fontPtr->staticSubFonts) { + ckfree((char *) fontPtr->subFontArray); + } +} + +/* + *------------------------------------------------------------------------- + * + * InitSubFont -- + * + * Wrap a screen font and load the FontFamily that represents + * it. Used to prepare a SubFont so that characters can be mapped + * from UTF-8 to the charset of the font. + * + * Results: + * The subFontPtr is filled with information about the font. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ + +static void +InitSubFont( + CONST MacFont *fontPtr, /* Font object in which the SubFont will be + * used. */ + int faceNum, /* The font number. */ + SubFont *subFontPtr) /* Filled with SubFont constructed from + * above attributes. */ +{ + subFontPtr->familyPtr = AllocFontFamily(fontPtr, faceNum); + subFontPtr->fontMap = subFontPtr->familyPtr->fontMap; +} + +/* + *------------------------------------------------------------------------- + * + * ReleaseSubFont -- + * + * Called to release the contents of a SubFont. The caller is + * responsible for freeing the memory used by the SubFont itself. + * + * Results: + * None. + * + * Side effects: + * Memory and resources are freed. + * + *--------------------------------------------------------------------------- + */ + +static void +ReleaseSubFont( + SubFont *subFontPtr) /* The SubFont to delete. */ +{ + FreeFontFamily(subFontPtr->familyPtr); +} + +/* + *------------------------------------------------------------------------- + * + * AllocFontFamily -- + * + * Find the FontFamily structure associated with the given font + * family. The information should be stored by the caller in a + * SubFont and used when determining if that SubFont supports a + * character. + * + * Results: + * A pointer to a FontFamily. The reference count in the FontFamily + * is automatically incremented. When the SubFont is released, the + * reference count is decremented. When no SubFont is using this + * FontFamily, it may be deleted. + * + * Side effects: + * A new FontFamily structure will be allocated if this font family + * has not been seen. + * + *------------------------------------------------------------------------- + */ + +static FontFamily * +AllocFontFamily( + CONST MacFont *fontPtr, /* Font object in which the FontFamily will + * be used. */ + int faceNum) /* The font number. */ +{ + FontFamily *familyPtr; + int i; + + familyPtr = fontFamilyList; + for (; familyPtr != NULL; familyPtr = familyPtr->nextPtr) { + if (familyPtr->faceNum == faceNum) { + familyPtr->refCount++; + return familyPtr; + } + } + + familyPtr = (FontFamily *) ckalloc(sizeof(FontFamily)); + memset(familyPtr, 0, sizeof(FontFamily)); + familyPtr->nextPtr = fontFamilyList; + fontFamilyList = familyPtr; + + /* + * Set key for this FontFamily. + */ + + familyPtr->faceNum = faceNum; + + /* + * An initial refCount of 2 means that FontFamily information will + * persist even when the SubFont that loaded the FontFamily is released. + * Change it to 1 to cause FontFamilies to be unloaded when not in use. + */ + + familyPtr->refCount = 2; + familyPtr->encoding = GetFontEncoding(faceNum, 1, &familyPtr->isSymbolFont); + familyPtr->isMultiByteFont = 0; + FillParseTable(familyPtr->typeTable, FontToScript(faceNum)); + for (i = 0; i < 256; i++) { + if (familyPtr->typeTable[i] != 0) { + familyPtr->isMultiByteFont = 1; + break; + } + } + return familyPtr; +} + +/* + *------------------------------------------------------------------------- + * + * FreeFontFamily -- + * + * Called to free a FontFamily when the SubFont is finished using it. + * Frees the contents of the FontFamily and the memory used by the + * FontFamily itself. + * + * Results: + * None. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ + +static void +FreeFontFamily( + FontFamily *familyPtr) /* The FontFamily to delete. */ +{ + FontFamily **familyPtrPtr; + int i; + + if (familyPtr == NULL) { + return; + } + familyPtr->refCount--; + if (familyPtr->refCount > 0) { + return; + } + Tcl_FreeEncoding(familyPtr->encoding); + for (i = 0; i < FONTMAP_PAGES; i++) { + if (familyPtr->fontMap[i] != NULL) { + ckfree((char *) familyPtr->fontMap[i]); + } + } + + /* + * Delete from list. + */ + + for (familyPtrPtr = &fontFamilyList; ; ) { + if (*familyPtrPtr == familyPtr) { + *familyPtrPtr = familyPtr->nextPtr; + break; + } + familyPtrPtr = &(*familyPtrPtr)->nextPtr; + } + + ckfree((char *) familyPtr); +} + +/* + *------------------------------------------------------------------------- + * + * FindSubFontForChar -- + * + * Determine which physical screen font is necessary to use to + * display the given character. If the font object does not have + * a screen font that can display the character, another screen font + * may be loaded into the font object, following a set of preferred + * fallback rules. + * + * Results: + * The return value is the SubFont to use to display the given + * character. + * + * Side effects: + * The contents of fontPtr are modified to cache the results + * of the lookup and remember any SubFonts that were dynamically + * loaded. + * + *------------------------------------------------------------------------- + */ + +static SubFont * +FindSubFontForChar( + MacFont *fontPtr, /* The font object with which the character + * will be displayed. */ + int ch) /* The Unicode character to be displayed. */ +{ + int i, j, k; + CONST char *fallbackName; + char **aliases; + SubFont *subFontPtr; + FontNameMap *mapPtr; + Tcl_DString faceNames; + char ***fontFallbacks; + char **anyFallbacks; + + if (FontMapLookup(&fontPtr->subFontArray[0], ch)) { + return &fontPtr->subFontArray[0]; + } + + for (i = 1; i < fontPtr->numSubFonts; i++) { + if (FontMapLookup(&fontPtr->subFontArray[i], ch)) { + return &fontPtr->subFontArray[i]; + } + } + + /* + * Keep track of all face names that we check, so we don't check some + * name multiple times if it can be reached by multiple paths. + */ + + Tcl_DStringInit(&faceNames); + + aliases = TkFontGetAliasList(fontPtr->font.fa.family); + + subFontPtr = NULL; + fontFallbacks = TkFontGetFallbacks(); + for (i = 0; fontFallbacks[i] != NULL; i++) { + for (j = 0; fontFallbacks[i][j] != NULL; j++) { + fallbackName = fontFallbacks[i][j]; + if (strcasecmp(fallbackName, fontPtr->font.fa.family) == 0) { + /* + * If the base font has a fallback... + */ + + goto tryfallbacks; + } else if (aliases != NULL) { + /* + * Or if an alias for the base font has a fallback... + */ + + for (k = 0; aliases[k] != NULL; k++) { + if (strcasecmp(aliases[k], fallbackName) == 0) { + goto tryfallbacks; + } + } + } + } + continue; + + /* + * ...then see if we can use one of the fallbacks, or an + * alias for one of the fallbacks. + */ + + tryfallbacks: + for (j = 0; fontFallbacks[i][j] != NULL; j++) { + fallbackName = fontFallbacks[i][j]; + subFontPtr = CanUseFallbackWithAliases(fontPtr, fallbackName, + ch, &faceNames); + if (subFontPtr != NULL) { + goto end; + } + } + } + + /* + * See if we can use something from the global fallback list. + */ + + anyFallbacks = TkFontGetGlobalClass(); + for (i = 0; anyFallbacks[i] != NULL; i++) { + fallbackName = anyFallbacks[i]; + subFontPtr = CanUseFallbackWithAliases(fontPtr, fallbackName, ch, + &faceNames); + if (subFontPtr != NULL) { + goto end; + } + } + + /* + * Try all face names available in the whole system until we + * find one that can be used. + */ + + for (mapPtr = gFontNameMap; mapPtr->utfName != NULL; mapPtr++) { + fallbackName = mapPtr->utfName; + if (SeenName(fallbackName, &faceNames) == 0) { + subFontPtr = CanUseFallback(fontPtr, fallbackName, ch); + if (subFontPtr != NULL) { + goto end; + } + } + } + + end: + Tcl_DStringFree(&faceNames); + + if (subFontPtr == NULL) { + /* + * No font can display this character. We will use the base font + * and have it display the "unknown" character. + */ + + subFontPtr = &fontPtr->subFontArray[0]; + FontMapInsert(subFontPtr, ch); + } + return subFontPtr; +} + +/* + *------------------------------------------------------------------------- + * + * FontMapLookup -- + * + * See if the screen font can display the given character. + * + * Results: + * The return value is 0 if the screen font cannot display the + * character, non-zero otherwise. + * + * Side effects: + * New pages are added to the font mapping cache whenever the + * character belongs to a page that hasn't been seen before. + * When a page is loaded, information about all the characters on + * that page is stored, not just for the single character in + * question. + * + *------------------------------------------------------------------------- + */ + +static int +FontMapLookup( + SubFont *subFontPtr, /* Contains font mapping cache to be queried + * and possibly updated. */ + int ch) /* Character to be tested. */ +{ + int row, bitOffset; + + row = ch >> FONTMAP_SHIFT; + if (subFontPtr->fontMap[row] == NULL) { + FontMapLoadPage(subFontPtr, row); + } + bitOffset = ch & (FONTMAP_BITSPERPAGE - 1); + return (subFontPtr->fontMap[row][bitOffset >> 3] >> (bitOffset & 7)) & 1; +} + +/* + *------------------------------------------------------------------------- + * + * FontMapInsert -- + * + * Tell the font mapping cache that the given screen font should be + * used to display the specified character. This is called when no + * font on the system can be be found that can display that + * character; we lie to the font and tell it that it can display + * the character, otherwise we would end up re-searching the entire + * fallback hierarchy every time that character was seen. + * + * Results: + * None. + * + * Side effects: + * New pages are added to the font mapping cache whenever the + * character belongs to a page that hasn't been seen before. + * When a page is loaded, information about all the characters on + * that page is stored, not just for the single character in + * question. + * + *------------------------------------------------------------------------- + */ + +static void +FontMapInsert( + SubFont *subFontPtr, /* Contains font mapping cache to be + * updated. */ + int ch) /* Character to be added to cache. */ +{ + int row, bitOffset; + + row = ch >> FONTMAP_SHIFT; + if (subFontPtr->fontMap[row] == NULL) { + FontMapLoadPage(subFontPtr, row); + } + bitOffset = ch & (FONTMAP_BITSPERPAGE - 1); + subFontPtr->fontMap[row][bitOffset >> 3] |= 1 << (bitOffset & 7); +} + +/* + *------------------------------------------------------------------------- + * + * FontMapLoadPage -- + * + * Load information about all the characters on a given page. + * This information consists of one bit per character that indicates + * whether the associated HFONT can (1) or cannot (0) display the + * characters on the page. + * + * Results: + * None. + * + * Side effects: + * Mempry allocated. + * + *------------------------------------------------------------------------- + */ +static void +FontMapLoadPage( + SubFont *subFontPtr, /* Contains font mapping cache to be + * updated. */ + int row) /* Index of the page to be loaded into + * the cache. */ +{ + FMInput fm; + FMOutPtr fmOut; + int i, end, bitOffset, isMultiByteFont; + char src[TCL_UTF_MAX]; + unsigned char buf[16]; + int srcRead, dstWrote; + Tcl_Encoding encoding; + Handle fHandle = NULL; + + subFontPtr->fontMap[row] = (char *) ckalloc(FONTMAP_BITSPERPAGE / 8); + memset(subFontPtr->fontMap[row], 0, FONTMAP_BITSPERPAGE / 8); + + encoding = subFontPtr->familyPtr->encoding; + + fm.family = subFontPtr->familyPtr->faceNum; + fm.size = 12; + fm.face = 0; + fm.needBits = 0; + fm.device = 0; + fm.numer.h = 1; + fm.numer.v = 1; + fm.denom.h = 1; + fm.denom.v = 1; + /* +#if !defined(UNIVERSAL_INTERFACES_VERSION) || (UNIVERSAL_INTERFACES_VERSION < 0x0300) + fHandle = FMSwapFont(&fm)->fontHandle; +#else + fHandle = FMSwapFont(&fm)->fontHandle; +#endif +*/ +/* + * For some reason, FMSwapFont alywas returns a structure where the returned font handle + * is NULL. Until we figure this one out, assume all characters are allowed + */ + fmOut=FMSwapFont(&fm); + fHandle=fmOut->fontHandle; + isMultiByteFont=subFontPtr->familyPtr->isMultiByteFont; +#ifndef MAC_OSX_TK + GetResInfo(fHandle, &theID, &theType, theName); + fprintf ( stderr, "ResError() %d, %x\n", ResError (), fHandle ); + if (theType=='sfnt') { +#endif + /* + * Found an outline font which has very complex font record. + * Let's just assume *ALL* the characters are allowed. + */ + + end = (row + 1) << FONTMAP_SHIFT; + for (i = row << FONTMAP_SHIFT; i < end; i++) { + if (Tcl_UtfToExternal(NULL, encoding, src, Tcl_UniCharToUtf(i, + src), + TCL_ENCODING_STOPONERROR, NULL, (char *) buf, + sizeof(buf), + &srcRead, &dstWrote, NULL) == TCL_OK) { + bitOffset = i & (FONTMAP_BITSPERPAGE - 1); + subFontPtr->fontMap[row][bitOffset >> 3] |= 1 + << (bitOffset & 7); + } + } +#ifndef MAC_OSX_TK + } else { + /* + * Found an old bitmap font which has a well-defined record. + * We can check the width table to see which characters exist. + */ + + fontRecPtr = *((FontRec **) fHandle ); + widths = (short *) ((long) &fontRecPtr->owTLoc + + ((long) (fontRecPtr->owTLoc - fontRecPtr->firstChar) + * sizeof(short))); + + end = (row + 1) << FONTMAP_SHIFT; + for (i = row << FONTMAP_SHIFT; i < end; i++) { + if (Tcl_UtfToExternal(NULL, encoding, src, + Tcl_UniCharToUtf(i, src), + TCL_ENCODING_STOPONERROR, NULL, (char *) buf, sizeof(buf), + &srcRead, &dstWrote, NULL) == TCL_OK) { + + if (((isMultiByteFont != 0) && (buf[0] > 31)) + || (widths[buf[0]] != -1)) { + if ((buf[0] == 0x11) && (widths[0x12] == -1)) { + continue; + } + + /* + * Mac's char existence metrics are only for one-byte + * characters. If we have a double-byte char, just + * assume that the font supports that char if the font's + * encoding supports that char. + */ + + bitOffset = i & (FONTMAP_BITSPERPAGE - 1); + subFontPtr->fontMap[row][bitOffset >> 3] |= 1 + << (bitOffset & 7); + } + } + } + } +#endif +} + +/* + *--------------------------------------------------------------------------- + * + * CanUseFallbackWithAliases -- + * + * Helper function for FindSubFontForChar. Determine if the + * specified face name (or an alias of the specified face name) + * can be used to construct a screen font that can display the + * given character. + * + * Results: + * See CanUseFallback(). + * + * Side effects: + * If the name and/or one of its aliases was rejected, the + * rejected string is recorded in nameTriedPtr so that it won't + * be tried again. + * + *--------------------------------------------------------------------------- + */ + +static SubFont * +CanUseFallbackWithAliases( + MacFont *fontPtr, /* The font object that will own the new + * screen font. */ + CONST char *faceName, /* Desired face name for new screen font. */ + int ch, /* The Unicode character that the new + * screen font must be able to display. */ + Tcl_DString *nameTriedPtr) /* Records face names that have already + * been tried. It is possible for the same + * face name to be queried multiple times when + * trying to find a suitable screen font. */ +{ + SubFont *subFontPtr; + char **aliases; + int i; + + if (SeenName(faceName, nameTriedPtr) == 0) { + subFontPtr = CanUseFallback(fontPtr, faceName, ch); + if (subFontPtr != NULL) { + return subFontPtr; + } + } + aliases = TkFontGetAliasList(faceName); + if (aliases != NULL) { + for (i = 0; aliases[i] != NULL; i++) { + if (SeenName(aliases[i], nameTriedPtr) == 0) { + subFontPtr = CanUseFallback(fontPtr, aliases[i], ch); + if (subFontPtr != NULL) { + return subFontPtr; + } + } + } + } + return NULL; +} + +/* + *--------------------------------------------------------------------------- + * + * SeenName -- + * + * Used to determine we have already tried and rejected the given + * face name when looking for a screen font that can support some + * Unicode character. + * + * Results: + * The return value is 0 if this face name has not already been seen, + * non-zero otherwise. + * + * Side effects: + * None. + * + *--------------------------------------------------------------------------- + */ + +static int +SeenName( + CONST char *name, /* The name to check. */ + Tcl_DString *dsPtr) /* Contains names that have already been + * seen. */ +{ + CONST char *seen, *end; + + seen = Tcl_DStringValue(dsPtr); + end = seen + Tcl_DStringLength(dsPtr); + while (seen < end) { + if (strcasecmp(seen, name) == 0) { + return 1; + } + seen += strlen(seen) + 1; + } + Tcl_DStringAppend(dsPtr, (char *) name, (int) (strlen(name) + 1)); + return 0; +} + +/* + *------------------------------------------------------------------------- + * + * CanUseFallback -- + * + * If the specified physical screen font has not already been loaded + * into the font object, determine if the specified physical screen + * font can display the given character. + * + * Results: + * The return value is a pointer to a newly allocated SubFont, owned + * by the font object. This SubFont can be used to display the given + * character. The SubFont represents the screen font with the base set + * of font attributes from the font object, but using the specified + * font name. NULL is returned if the font object already holds + * a reference to the specified physical font or if the specified + * physical font cannot display the given character. + * + * Side effects: + * The font object's subFontArray is updated to contain a reference + * to the newly allocated SubFont. + * + *------------------------------------------------------------------------- + */ + +static SubFont * +CanUseFallback( + MacFont *fontPtr, /* The font object that will own the new + * screen font. */ + CONST char *faceName, /* Desired face name for new screen font. */ + int ch) /* The Unicode character that the new + * screen font must be able to display. */ +{ + int i; + SubFont subFont; + short faceNum; + + if (GetFamilyNum(faceName, &faceNum) == 0) { + return NULL; + } + + /* + * Skip all fonts we've already used. + */ + + for (i = 0; i < fontPtr->numSubFonts; i++) { + if (faceNum == fontPtr->subFontArray[i].familyPtr->faceNum) { + return NULL; + } + } + + /* + * Load this font and see if it has the desired character. + */ + + InitSubFont(fontPtr, faceNum, &subFont); + if (((ch < 256) && (subFont.familyPtr->isSymbolFont)) + || (FontMapLookup(&subFont, ch) == 0)) { + ReleaseSubFont(&subFont); + return NULL; + } + + if (fontPtr->numSubFonts >= SUBFONT_SPACE) { + SubFont *newPtr; + newPtr = (SubFont *) ckalloc(sizeof(SubFont) + * (fontPtr->numSubFonts + 1)); + memcpy((char *) newPtr, fontPtr->subFontArray, + fontPtr->numSubFonts * sizeof(SubFont)); + if (fontPtr->subFontArray != fontPtr->staticSubFonts) { + ckfree((char *) fontPtr->subFontArray); + } + fontPtr->subFontArray = newPtr; + } + fontPtr->subFontArray[fontPtr->numSubFonts] = subFont; + fontPtr->numSubFonts++; + return &fontPtr->subFontArray[fontPtr->numSubFonts - 1]; +} + +/* + *------------------------------------------------------------------------- + * + * GetFamilyNum -- + * + * Determines 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. + * + * Results: + * The return value is 0 if the specified font family does not exist, + * non-zero otherwise. *faceNumPtr is filled with the unique face + * number that identifies the screen font, or 0 if the font family + * did not exist. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------- + */ + +static int +GetFamilyNum( + CONST char *faceName, /* UTF-8 name of font family to query. */ + short *faceNumPtr) /* Filled with font number for above family. */ +{ + FontNameMap *mapPtr; + + if (faceName != NULL) { + for (mapPtr = gFontNameMap; mapPtr->utfName != NULL; mapPtr++) { + if (strcasecmp(faceName, mapPtr->utfName) == 0) { + *faceNumPtr = mapPtr->faceNum; + return 1; + } + } + } + *faceNumPtr = 0; + return 0; +} + +static int +GetFamilyOrAliasNum( + CONST char *faceName, /* UTF-8 name of font family to query. */ + short *faceNumPtr) /* Filled with font number for above family. */ +{ + char **aliases; + int i; + + if (GetFamilyNum(faceName, faceNumPtr) != 0) { + return 1; + } + aliases = TkFontGetAliasList(faceName); + if (aliases != NULL) { + for (i = 0; aliases[i] != NULL; i++) { + if (GetFamilyNum(aliases[i], faceNumPtr) != 0) { + return 1; + } + } + } + return 0; +} + +/* + *------------------------------------------------------------------------- + * + * GetUtfFaceName -- + * + * Given the native name for a Macintosh font (in which the name of + * the font is in the encoding of the font itself), return the UTF-8 + * name that corresponds to that font. The specified font name must + * refer to a font that actually exists on the machine. + * + * This function is used to obtain the UTF-8 name when querying the + * properties of a Macintosh font object. + * + * Results: + * The return value is a pointer to the UTF-8 of the specified font. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ + +static Tk_Uid +GetUtfFaceName( + StringPtr nativeName) /* Pascal name for font in native encoding. */ +{ + FontNameMap *mapPtr; + + for (mapPtr = gFontNameMap; mapPtr->utfName != NULL; mapPtr++) { + if (pstrcmp(nativeName, mapPtr->nativeName) == 0) { + return mapPtr->utfName; + } + } + panic("GetUtfFaceName: unexpected nativeName"); + return NULL; +} + +/* + *------------------------------------------------------------------------ + * + * GetFontEncoding -- + * + * Return a string that can be passed to Tcl_GetTextEncoding() and + * used to convert bytes from UTF-8 into the encoding of the + * specified font. + * + * The desired encoding to use to convert the name of a symbolic + * font into UTF-8 is macRoman, while the desired encoding to use + * to convert bytes in a symbolic font to UTF-8 is the corresponding + * symbolic encoding. Due to this dual interpretatation of symbolic + * fonts, the caller can specify what type of encoding to return + * should the specified font be symbolic. + * + * Results: + * The return value is a string that specifies the font's encoding. + * If the font's encoding could not be identified, NULL is returned. + * + * Side effects: + * None. + * + *------------------------------------------------------------------------ + */ + +static Tcl_Encoding +GetFontEncoding( + int faceNum, /* Macintosh font number. */ + int allowSymbol, /* If non-zero, then the encoding string + * for symbol fonts will be the corresponding + * symbol encoding. Otherwise, the encoding + * string for symbol fonts will be + * "macRoman". */ + int *isSymbolPtr) /* Filled with non-zero if this font is a + * symbol font, 0 otherwise. */ +{ + Str255 faceName; + int script, lang; + char *name; + + if (allowSymbol != 0) { + GetFontName(faceNum, faceName); + if (pstrcasecmp(faceName, "\psymbol") == 0) { + *isSymbolPtr = 1; + return Tcl_GetEncoding(NULL, "symbol"); + } + if (pstrcasecmp(faceName, "\pzapf dingbats") == 0) { + *isSymbolPtr = 1; + return Tcl_GetEncoding(NULL, "macDingbats"); + } + } + *isSymbolPtr = 0; + script = FontToScript(faceNum); + lang = GetScriptVariable(script, smScriptLang); + name = NULL; + if (script == smRoman) { + name = TkFindStateString(romanMap, lang); + } else if (script == smCyrillic) { + name = TkFindStateString(cyrillicMap, lang); + } + if (name == NULL) { + name = TkFindStateString(scriptMap, script); + } + return Tcl_GetEncoding(NULL, name); +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXInitControlFontStyle -- + * + * This procedure sets up the appropriate ControlFontStyleRec + * for a Mac control. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXInitControlFontStyle(Tk_Font tkfont, ControlFontStylePtr fsPtr) +{ + MacFont *fontPtr; + FontFamily *lastFamilyPtr; + fontPtr = (MacFont *) tkfont; + lastFamilyPtr = fontPtr->subFontArray[0].familyPtr; + fsPtr->flags = + kControlUseFontMask| + kControlUseSizeMask| + kControlUseFaceMask| + kControlUseJustMask; + fsPtr->font = lastFamilyPtr->faceNum; + fsPtr->size = fontPtr->size; + fsPtr->style = fontPtr->style; + fsPtr->just = teCenter; +} diff --git a/macosx/tkMacOSXHLEvents.c b/macosx/tkMacOSXHLEvents.c new file mode 100644 index 0000000..4a1d30c --- /dev/null +++ b/macosx/tkMacOSXHLEvents.c @@ -0,0 +1,447 @@ +/* + * tkMacOSXHLEvents.c -- + * + * 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. + * + * 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.2 2002/08/31 06:12:30 das Exp $ + */ + +#include "tkMacOSXUtil.h" +#include "tkMacOSXInt.h" + +#include <Carbon/Carbon.h> + +/* + * This is a Tcl_Event structure that the Quit AppleEvent handler + * uses to schedule the tkReallyKillMe 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 */ +} KillEvent; + +/* + * Static functions used only in this file. + */ + +static OSErr QuitHandler (const AppleEvent * event, AppleEvent * reply, long handlerRefcon); +static OSErr OappHandler (const AppleEvent * event, AppleEvent * reply, long handlerRefcon); +static OSErr OdocHandler (const AppleEvent * event, AppleEvent * reply, long handlerRefcon); +static OSErr PrintHandler (const AppleEvent * event, AppleEvent * reply, long handlerRefcon); +static OSErr ScriptHandler (const AppleEvent * event, AppleEvent * reply, long handlerRefcon); +static OSErr PrefsHandler (const AppleEvent * event, AppleEvent * reply, long handlerRefcon); + +static int MissedAnyParameters _ANSI_ARGS_((const AppleEvent *theEvent)); +static int ReallyKillMe _ANSI_ARGS_((Tcl_Event *eventPtr, int flags)); + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXInitAppleEvents -- + * + * Initilize the Apple Events on the Macintosh. This registers the + * core event handlers. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXInitAppleEvents( + Tcl_Interp *interp) /* Interp to handle basic events. */ +{ + OSErr err; + AEEventHandlerUPP OappHandlerUPP, OdocHandlerUPP, + PrintHandlerUPP, QuitHandlerUPP, ScriptHandlerUPP, + PrefsHandlerUPP; + + /* + * Install event handlers for the core apple events. + */ + QuitHandlerUPP = NewAEEventHandlerUPP(QuitHandler); + err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication, + QuitHandlerUPP, (long) interp, false); + + OappHandlerUPP = NewAEEventHandlerUPP(OappHandler); + err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication, + OappHandlerUPP, (long) interp, false); + + OdocHandlerUPP = NewAEEventHandlerUPP(OdocHandler); + err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments, + OdocHandlerUPP, (long) interp, false); + + PrintHandlerUPP = NewAEEventHandlerUPP(PrintHandler); + err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments, + PrintHandlerUPP, (long) interp, false); + + PrefsHandlerUPP = NewAEEventHandlerUPP(PrefsHandler); + err = AEInstallEventHandler(kCoreEventClass, kAEShowPreferences, + PrefsHandlerUPP, (long) interp, false); + + if (interp != NULL) { + ScriptHandlerUPP = NewAEEventHandlerUPP(ScriptHandler); + err = AEInstallEventHandler('misc', 'dosc', + ScriptHandlerUPP, (long) interp, false); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXDoHLEvent -- + * + * Dispatch incomming highlevel events. + * + * Results: + * None. + * + * Side effects: + * Depends on the incoming event. + * + *---------------------------------------------------------------------- + */ + +int +TkMacOSXDoHLEvent(EventRecord *theEvent) +{ + return AEProcessAppleEvent(theEvent); +} + +/* + *---------------------------------------------------------------------- + * + * QuitHandler, OappHandler, etc. -- + * + * These are the core Apple event handlers. Only the Quit event does + * anything interesting. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +OSErr QuitHandler (const AppleEvent * event, AppleEvent * reply, long handlerRefcon) +{ + Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon; + KillEvent *eventPtr; + + /* + * 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 + * 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 (const AppleEvent * event, AppleEvent * reply, long handlerRefcon) +{ + return noErr; +} + +/* Called when the user selects 'Preferences...' in MacOS X */ +static OSErr +PrefsHandler (const AppleEvent * event, AppleEvent * reply, long handlerRefcon) +{ + Tcl_CmdInfo dummy; + Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon; + /* + * Don't bother if we don't have an interp or + * the show preferences procedure doesn't exist. + */ + + if ((interp == NULL) || + (Tcl_GetCommandInfo(interp, "::tk::mac::ShowPreferences", &dummy)) == 0) { + return noErr; + } + Tcl_GlobalEval(interp, "::tk::mac::ShowPreferences"); + return noErr; +} + +static OSErr +OdocHandler (const AppleEvent * event, AppleEvent * reply, long handlerRefcon) +{ + Tcl_Interp *interp = (Tcl_Interp *) handlerRefcon; + AEDescList fileSpecList; + FSSpec file; + OSErr err; + DescType type; + Size actual; + long count; + AEKeyword keyword; + long index; + Tcl_DString command; + Tcl_DString pathName; + Tcl_CmdInfo dummy; + + /* + * Don't bother if we don't have an interp or + * the open document procedure doesn't exist. + */ + + 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); + if (err != noErr) { + return noErr; + } + + err = MissedAnyParameters(event); + if (err != noErr) { + return noErr; + } + + err = AECountItems(&fileSpecList, &count); + if (err != noErr) { + return noErr; + } + + Tcl_DStringInit(&command); + Tcl_DStringAppend(&command, "::tk::mac::OpenDocument", -1); + for (index = 1; index <= count; index++) { + int length; + Handle fullPath; + + err = AEGetNthPtr(&fileSpecList, index, typeFSS, + &keyword, &type, (Ptr) &file, sizeof(FSSpec), &actual); + if ( err != noErr ) { + continue; + } + + err = FSpPathFromLocation(&file, &length, &fullPath); + HLock(fullPath); + Tcl_ExternalToUtfDString(NULL, *fullPath, length, &pathName); + HUnlock(fullPath); + DisposeHandle(fullPath); + + Tcl_DStringAppendElement(&command, Tcl_DStringValue(&pathName)); + Tcl_DStringFree(&pathName); + } + + Tcl_GlobalEval(interp, Tcl_DStringValue(&command)); + + Tcl_DStringFree(&command); + return noErr; +} + +static OSErr +PrintHandler (const AppleEvent * event, AppleEvent * reply, long handlerRefcon) +{ + return noErr; +} + +/* + *---------------------------------------------------------------------- + * + * ScriptHandler -- + * + * This handler process the script event. + * + * Results: + * Schedules the given event to be processed. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static OSErr +ScriptHandler (const AppleEvent * event, AppleEvent * reply, long handlerRefcon) +{ + OSErr theErr; + AEDescList theDesc; + int tclErr = -1; + Tcl_Interp *interp; + char errString[128]; + + interp = (Tcl_Interp *) handlerRefcon; + + /* + * The do script event receives one parameter that should be data or a file. + */ + theErr = AEGetParamDesc(event, keyDirectObject, typeWildCard, + &theDesc); + if (theErr != noErr) { + sprintf(errString, "AEDoScriptHandler: GetParamDesc error %d", 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; + } else { + if (theDesc.descriptorType == (DescType)'TEXT') { + 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)'alis') { + Boolean dummy; + FSSpec theFSS; + Handle fullPath; + int length; + AliasHandle aliasHandle; + + AEGetDescData (&theDesc,&aliasHandle,sizeof(aliasHandle ) ); + + theErr = ResolveAlias(NULL, aliasHandle, + &theFSS, &dummy); + if (theErr == noErr) { + FSpPathFromLocation(&theFSS, &length, &fullPath); + HLock(fullPath); + Tcl_EvalFile(interp, *fullPath); + HUnlock(fullPath); + DisposeHandle(fullPath); + } 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)); + } + } + + AEDisposeDesc(&theDesc); + + return theErr; +} + +/* + *---------------------------------------------------------------------- + * + * ReallyKillMe -- + * + * This proc tries to kill the shell by running exit, and if that + * has not succeeded (e.g. because someone has renamed the exit + * command), calls Tcl_Exit to really kill the shell. Called from + * an event scheduled by the "Quit" AppleEvent handler. + * + * Results: + * Kills the shell. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +ReallyKillMe(Tcl_Event *eventPtr, int flags) +{ + Tcl_Interp *interp = ((KillEvent *) eventPtr)->interp; + if (interp != NULL) { + Tcl_GlobalEval(interp, "exit"); + } + Tcl_Exit(0); + + return 1; +} + +/* + *---------------------------------------------------------------------- + * + * MissedAnyParameters -- + * + * Checks to see if parameters are still left in the event. + * + * Results: + * True or false. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +MissedAnyParameters( + const AppleEvent *theEvent) +{ + DescType returnedType; + Size actualSize; + OSErr err; + + err = AEGetAttributePtr(theEvent, keyMissedKeywordAttr, typeWildCard, + &returnedType, NULL, 0, &actualSize); + + return (err != errAEDescNotFound); +} diff --git a/macosx/tkMacOSXInit.c b/macosx/tkMacOSXInit.c new file mode 100644 index 0000000..ffcab99 --- /dev/null +++ b/macosx/tkMacOSXInit.c @@ -0,0 +1,221 @@ +/* + * tkUnixInit.c -- + * + * This file contains Unix-specific interpreter initialization + * functions. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * 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.2 2002/08/31 06:12:30 das Exp $ + */ + +#include "tkInt.h" +#include "tkMacOSXInt.h" + +/* + * The Init script (common to Windows and Unix platforms) is + * defined in tkInitScript.h + */ +#include "tkInitScript.h" + +/* + * 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 + * defined by Apple. + */ + +typedef struct Map { + int numKey; + char *strKey; +} Map; + +static Map scriptMap[] = { + {smRoman, "macRoman"}, + {smJapanese, "macJapan"}, + {smTradChinese, "macChinese"}, + {smKorean, "macKorean"}, + {smArabic, "macArabic"}, + {smHebrew, "macHebrew"}, + {smGreek, "macGreek"}, + {smCyrillic, "macCyrillic"}, + {smRSymbol, "macRSymbol"}, + {smDevanagari, "macDevanagari"}, + {smGurmukhi, "macGurmukhi"}, + {smGujarati, "macGujarati"}, + {smOriya, "macOriya"}, + {smBengali, "macBengali"}, + {smTamil, "macTamil"}, + {smTelugu, "macTelugu"}, + {smKannada, "macKannada"}, + {smMalayalam, "macMalayalam"}, + {smSinhalese, "macSinhalese"}, + {smBurmese, "macBurmese"}, + {smKhmer, "macKhmer"}, + {smThai, "macThailand"}, + {smLaotian, "macLaos"}, + {smGeorgian, "macGeorgia"}, + {smArmenian, "macArmenia"}, + {smSimpChinese, "macSimpChinese"}, + {smTibetan, "macTIbet"}, + {smMongolian, "macMongolia"}, + {smGeez, "macEthiopia"}, + {smEastEurRoman, "macCentEuro"}, + {smVietnamese, "macVietnam"}, + {smExtArabic, "macSindhi"}, + {NULL, NULL} +}; + +Tcl_Encoding TkMacOSXCarbonEncoding = NULL; + + +/* + *---------------------------------------------------------------------- + * + * TkpInit -- + * + * 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. + * + * Side effects: + * Sets "tk_library" Tcl variable, runs "tk.tcl" script. + * + *---------------------------------------------------------------------- + */ + +int +TkpInit(interp) + Tcl_Interp *interp; +{ + char tkLibPath[1024]; + int result; + static int menusInitialized = false; + static int carbonEncodingInitialized = false; + + /* + * Since it is possible for TkInit to be called multiple times + * and we don't want to do the menu initialization multiple times + * we protect against doing it more than once. + */ + + if (menusInitialized == false) { + menusInitialized = true; + Tk_MacOSXSetupTkNotifier(); + TkMacOSXInitAppleEvents(interp); + TkMacOSXInitMenus(interp); + } + + if (carbonEncodingInitialized == false) { + CFStringEncoding encoding; + char *encodingStr = NULL; + int i; + + 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); + } + } + + /* + * 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? + */ + + result = Tcl_MacOSXOpenBundleResources(interp, "com.tcltk.tklibrary", + 1, 1024, tkLibPath); + + if (result != TCL_ERROR) { + Tcl_SetVar(interp, "tk_library", tkLibPath, TCL_GLOBAL_ONLY); + } + + return Tcl_Eval(interp, initScript); +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * Results: + * Returns the application name in the given Tcl_DString. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkpGetAppName(interp, namePtr) + Tcl_Interp *interp; + Tcl_DString *namePtr; /* A previously initialized Tcl_DString. */ +{ + CONST char *p, *name; + + name = Tcl_GetVar(interp, "argv0", TCL_GLOBAL_ONLY); + if ((name == NULL) || (*name == 0)) { + name = "tk"; + } else { + p = strrchr(name, '/'); + if (p != NULL) { + name = p+1; + } + } + Tcl_DStringAppend(namePtr, name, -1); +} + +/* + *---------------------------------------------------------------------- + * + * TkpDisplayWarning -- + * + * This routines is called from Tk_Main to display warning + * messages that occur during startup. + * + * Results: + * None. + * + * Side effects: + * Generates messages on stdout. + * + *---------------------------------------------------------------------- + */ + +void +TkpDisplayWarning(msg, title) + CONST char *msg; /* Message to be displayed. */ + CONST char *title; /* Title of warning. */ +{ + Tcl_Channel errChannel = Tcl_GetStdChannel(TCL_STDERR); + if (errChannel) { + Tcl_WriteChars(errChannel, title, -1); + Tcl_WriteChars(errChannel, ": ", 2); + Tcl_WriteChars(errChannel, msg, -1); + Tcl_WriteChars(errChannel, "\n", 1); + } +} diff --git a/macosx/tkMacOSXInt.h b/macosx/tkMacOSXInt.h new file mode 100644 index 0000000..b609d6e --- /dev/null +++ b/macosx/tkMacOSXInt.h @@ -0,0 +1,155 @@ +/* + * tkMacOSXInt.h -- + * + * Declarations of Macintosh specific shared variables and procedures. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * 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.2 2002/08/31 06:12:30 das Exp $ + */ + +#ifndef _TKMACINT +#define _TKMACINT + +#ifndef _TKINT +#include "tkInt.h" +#endif + +/* + * Include platform specific public interfaces. + */ + +#ifndef _TKMAC +#include "tkMacOSX.h" +#endif + +#ifndef _TKPORT +#include "tkPort.h" +#endif + +#include <Carbon/Carbon.h> + +struct TkWindowPrivate { + TkWindow *winPtr; /* Ptr to tk window or NULL if Pixmap */ + CGrafPtr grafPtr; + ControlRef rootControl; + int xOff; /* X offset from toplevel window */ + int yOff; /* Y offset from toplevel window */ + RgnHandle clipRgn; /* Visable region of window */ + RgnHandle aboveClipRgn; /* Visable region of window & it's children */ + int referenceCount; /* Don't delete toplevel until children are + * gone. */ + struct TkWindowPrivate *toplevel; /* Pointer to the toplevel + * datastruct. */ + int flags; /* Various state see defines below. */ +}; +typedef struct TkWindowPrivate MacDrawable; + +/* + * This list is used to keep track of toplevel windows that have a Mac + * window attached. This is useful for several things, not the least + * of which is maintaining floating windows. + */ + +typedef struct TkMacOSXWindowList { + 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 + +/* + * 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 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 Destroy of a child. + */ + +/* + * This structure is for handling Netscape-type in process + * 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 + * are in tclMac.h. + */ + +typedef struct { + Tk_MacOSXEmbedRegisterWinProc *registerWinProc; + Tk_MacOSXEmbedGetGrafPortProc *getPortProc; + Tk_MacOSXEmbedMakeContainerExistProc *containerExistProc; + Tk_MacOSXEmbedGetClipProc *getClipProc; + Tk_MacOSXEmbedGetOffsetInParentProc *getOffsetProc; +} TkMacOSXEmbedHandler; + +extern TkMacOSXEmbedHandler *gMacEmbedHandler; + +/* + * Defines used for TkMacOSXInvalidateWindow + */ + +#define TK_WINDOW_ONLY 0 +#define TK_PARENT_WINDOW 1 + +/* + * Accessor for the privatePtr flags field for the TK_HOST_EXISTS field + */ + +#define TkMacOSXHostToplevelExists(tkwin) \ + (((TkWindow *) (tkwin))->privatePtr->toplevel->flags & TK_HOST_EXISTS) + +/* + * Defines use for the flags argument to TkGenWMConfigureEvent. + */ + +#define TK_LOCATION_CHANGED 1 +#define TK_SIZE_CHANGED 2 +#define TK_BOTH_CHANGED 3 + +/* + * Variables shared among various Mac Tk modules but are not + * exported to the outside world. + */ + +/* + * Globals shared among Macintosh Tk + */ + +extern MenuHandle tkAppleMenu; /* Handle to the Apple Menu */ +extern MenuHandle tkFileMenu; /* Handles to menus */ +extern MenuHandle tkEditMenu; /* Handles to menus */ +extern RgnHandle tkMenuCascadeRgn; /* A region to clip with. */ +extern 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. */ +extern int tkPictureIsOpen; /* If this is 1, we are drawing to a picture + * The clipping should then be done relative + * to the bounds of the picture rather than the window + * As of OS X.0.4, something is seriously wrong: + * The clipping bounds only seem to work if the + * top,left values are 0,0 + * The destination rectangle for CopyBits + * should also have top,left values of 0,0 + */ +extern TkMacOSXWindowList *tkMacOSXWindowListPtr; + /* The list of toplevels */ + +extern Tcl_Encoding TkMacOSXCarbonEncoding; + +#include "tkIntPlatDecls.h" + +#endif /* _TKMACINT */ diff --git a/macosx/tkMacOSXKeyEvent.c b/macosx/tkMacOSXKeyEvent.c new file mode 100644 index 0000000..7c3474c --- /dev/null +++ b/macosx/tkMacOSXKeyEvent.c @@ -0,0 +1,420 @@ +/* + * tkMacOSXKeyEvent.c -- + * + * This file implements functions that decode & handle keyboard events + * on MacOS X. + * + * Copyright 2001, Apple Computer, Inc. + * + * 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. + */ + +#include "tkMacOSXInt.h" +#include "tkPort.h" +#include "tkMacOSXEvent.h" + +typedef struct { + WindowRef whichWindow; + Point global; + Point local; + int state; + 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. */ + +/* + * Declarations for functions used only in this file. + */ + +static int GenerateKeyEvent _ANSI_ARGS_(( EventKind eKind, + KeyEventData * e, + Window window, + UInt32 savedKeyCode)); +/* + *---------------------------------------------------------------------- + * + * TkMacOSXProcessKeyboardEvent -- + * + * This routine processes the event in eventPtr, and + * generates the appropriate Tk events from it. + * + * Results: + * True if event(s) are generated - false otherwise. + * + * Side effects: + * Additional events may be place on the Tk event queue. + * + *---------------------------------------------------------------------- + */ + +int TkMacOSXProcessKeyboardEvent( + TkMacOSXEvent * eventPtr, + MacEventStatus * statusPtr) +{ + static UInt32 savedKeyCode = 0; + OSStatus status; + KeyEventData keyEventData; + Window window; + MenuRef menuRef; + MenuItemIndex menuItemIndex; + int eventGenerated; + + statusPtr->handledByTk = 1; + keyEventData.whichWindow = FrontNonFloatingWindow(); + if (keyEventData.whichWindow == NULL) { + return 0; + } + GetMouse(&keyEventData.local); + keyEventData.global = keyEventData.local; + LocalToGlobal(&keyEventData.global); + keyEventData.state = TkMacOSXButtonKeyState(); + if (IsMenuKeyEvent(NULL, eventPtr->eventRef, + kNilOptions, &menuRef, &menuItemIndex)) { + int oldMode; + MenuID menuID; + KeyMap theKeys; + int selection; + + menuID = GetMenuID(menuRef); + selection = (menuID << 16 ) | menuItemIndex; + + GetKeys(theKeys); + oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); + TkMacOSXClearMenubarActive(); + + /* + * Handle -postcommand + */ + + TkMacOSXPreprocessMenu(); + TkMacOSXHandleMenuSelect(selection, theKeys[1] & 4); + Tcl_SetServiceMode(oldMode); + return 0; /* TODO: may not be on event on queue. */ + } + + status = GetEventParameter(eventPtr->eventRef, + kEventParamKeyMacCharCodes, + typeChar, NULL, + sizeof(keyEventData.ch), NULL, + &keyEventData.ch); + if (status != noErr) { + fprintf(stderr, "Failed to retrieve KeyMacCharCodes\n" ); + statusPtr->err = 1; + return 1; + } + status = GetEventParameter(eventPtr->eventRef, + kEventParamKeyCode, + typeUInt32, NULL, + sizeof(keyEventData.keyCode), NULL, + &keyEventData.keyCode); + if (status != noErr) { + fprintf(stderr, "Failed to retrieve KeyCode\n" ); + statusPtr->err = 1; + return 1; + } + status = GetEventParameter(eventPtr->eventRef, + kEventParamKeyModifiers, + typeUInt32, NULL, + sizeof(keyEventData.keyModifiers), NULL, + &keyEventData.keyModifiers); + if (status != noErr) { + fprintf(stderr, "Failed to retrieve KeyModifiers\n" ); + statusPtr->err = 1; + return 1; + } + keyEventData.message = keyEventData.ch|(keyEventData.keyCode << 8); + + window = TkMacOSXGetXWindow(keyEventData.whichWindow); + + eventGenerated = GenerateKeyEvent(eventPtr->eKind, &keyEventData, + window, savedKeyCode); + + if (eventGenerated == 0) { + savedKeyCode = keyEventData.message; + return false; + } else if (eventGenerated == -1) { + savedKeyCode = 0; + return false; + } else { + savedKeyCode = 0; + return true; + } +} + +/* + *---------------------------------------------------------------------- + * + * GenerateKeyEvent -- + * + * Given Macintosh keyUp, keyDown & autoKey events this function + * generates the appropiate X key events. The window that is passed + * should represent the frontmost window - which will recieve the + * event. + * + * Results: + * 1 if an event was generated, 0 if we are waiting for another + * byte of a multi-byte sequence, and -1 for any other error. + * + * Side effects: + * Additional events may be place on the Tk event queue. + * + *---------------------------------------------------------------------- + */ + +int +GenerateKeyEvent( EventKind eKind, + KeyEventData * e, + Window window, + UInt32 savedKeyCode ) +{ + Tk_Window tkwin; + XEvent event; + unsigned char byte; + char buf[16]; + TkDisplay *dispPtr; + + /* + * The focus must be in the FrontWindow on the Macintosh. + * We then query Tk to determine the exact Tk window + * that owns the focus. + */ + + dispPtr = TkGetDisplayList(); + tkwin = Tk_IdToWindow(dispPtr->display, window); + + if (tkwin == NULL) { + fprintf(stderr,"tkwin == NULL, %d\n", __LINE__); + return -1; + } + + tkwin = (Tk_Window) ((TkWindow *) tkwin)->dispPtr->focusPtr; + if (tkwin == NULL) { + fprintf(stderr,"tkwin == NULL, %d\n", __LINE__); + return -1; + } + byte = (e->message&charCodeMask); + if ((savedKeyCode == 0) && + (Tcl_ExternalToUtf(NULL, TkMacOSXCarbonEncoding, + (char *) &byte, 1, 0, NULL, + buf, sizeof(buf), NULL, NULL, NULL) != TCL_OK)) { + /* + * This event specifies a lead byte. Wait for the second byte + * to come in before sending the XEvent. + */ + fprintf(stderr,"Failed %02x\n", byte); + return 0; + } + + event.xany.send_event = False; + event.xkey.same_screen = true; + event.xkey.subwindow = None; + event.xkey.time = TkpGetMS(); + + event.xkey.x_root = e->global.h; + event.xkey.y_root = e->global.v; + Tk_TopCoordsToWindow(tkwin, e->local.h, e->local.v, + &event.xkey.x, &event.xkey.y); + + event.xkey.keycode = byte | + ((savedKeyCode & charCodeMask) << 8) | + ((e->message&keyCodeMask) << 8); + + event.xany.serial = Tk_Display(tkwin)->request; + event.xkey.window = Tk_WindowId(tkwin); + event.xkey.display = Tk_Display(tkwin); + event.xkey.root = XRootWindow(Tk_Display(tkwin), 0); + event.xkey.state = e->state; + + 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: + break; + } + return 1; +} + +/* + *---------------------------------------------------------------------- + * + * XGrabKeyboard -- + * + * Simulates a keyboard grab by setting the focus. + * + * Results: + * Always returns GrabSuccess. + * + * Side effects: + * Sets the keyboard focus to the specified window. + * + *---------------------------------------------------------------------- + */ + +int +XGrabKeyboard( + Display* display, + Window grab_window, + Bool owner_events, + int pointer_mode, + int keyboard_mode, + Time time) +{ + gKeyboardWinPtr = Tk_IdToWindow(display, grab_window); + return GrabSuccess; +} + +/* + *---------------------------------------------------------------------- + * + * XUngrabKeyboard -- + * + * Releases the simulated keyboard grab. + * + * Results: + * None. + * + * Side effects: + * Sets the keyboard focus back to the value before the grab. + * + *---------------------------------------------------------------------- + */ + +void +XUngrabKeyboard( + Display* display, + Time time) +{ + gKeyboardWinPtr = NULL; +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXGetCapture -- + * + * Results: + * Returns the current grab window + * Side effects: + * None. + * + */ +Tk_Window +TkMacOSXGetCapture() +{ + return gGrabWinPtr; +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * Results: + * None. + * + * Side effects: + * Sets the capture flag and captures the mouse. + * + *---------------------------------------------------------------------- + */ + +void +TkpSetCapture( + TkWindow *winPtr) /* Capture window, or NULL. */ +{ + while ((winPtr != NULL) && !Tk_IsTopLevel(winPtr)) { + winPtr = winPtr->parentPtr; + } + gGrabWinPtr = (Tk_Window) winPtr; +} + +/* + *---------------------------------------------------------------------- + * + * 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. + * + * Results: + * None + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ + +void +Tk_SetCaretPos(tkwin, x, y, height) + Tk_Window tkwin; + int x; + int y; + int height; +{ +} diff --git a/macosx/tkMacOSXKeyboard.c b/macosx/tkMacOSXKeyboard.c new file mode 100644 index 0000000..db5d679 --- /dev/null +++ b/macosx/tkMacOSXKeyboard.c @@ -0,0 +1,650 @@ +/* + * tkMacOSXKeyboard.c -- + * + * Routines to support keyboard events on the Macintosh. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * 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.2 2002/08/31 06:12:30 das Exp $ + */ + +#include "tkInt.h" +#include "X11/Xlib.h" +#include "X11/keysym.h" +#include <Carbon/Carbon.h> +#include "tkMacOSXInt.h" + +typedef struct { + int keycode; /* Macintosh keycode */ + KeySym keysym; /* X windows Keysym */ +} KeyInfo; + +static KeyInfo keyArray[] = { + {0x4C, XK_Return}, + {0x24, XK_Return}, + {0x33, XK_BackSpace}, + {0x75, XK_Delete}, + {0x30, XK_Tab}, + {0x74, XK_Page_Up}, + {0x79, XK_Page_Down}, + {0x73, XK_Home}, + {0x77, XK_End}, + {0x7B, XK_Left}, + {0x7C, XK_Right}, + {0x7E, XK_Up}, + {0x7D, XK_Down}, + {0x72, XK_Help}, + {0x35, XK_Escape}, + {0x47, XK_Clear}, + {0, 0} +}; + +static KeyInfo vituralkeyArray[] = { + {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; /* vituralkeyArray hashed by virtual + keycode value. */ +static Ptr KCHRPtr; /* Pointer to 'KCHR' resource. */ + +/* + * Prototypes for static functions used in this file. + */ +static void InitKeyMaps _ANSI_ARGS_((void)); + + +/* + *---------------------------------------------------------------------- + * + * InitKeyMaps -- + * + * Creates hash tables used by some of the functions in this file. + * + * Results: + * None. + * + * Side effects: + * Allocates memory & creates some hash tables. + * + *---------------------------------------------------------------------- + */ + +static void +InitKeyMaps() +{ + 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); + } + Tcl_InitHashTable(&vkeyTable, TCL_ONE_WORD_KEYS); + for (kPtr = vituralkeyArray; kPtr->keycode != 0; kPtr++) { + hPtr = Tcl_CreateHashEntry(&vkeyTable, (char *) kPtr->keycode, + &dummy); + Tcl_SetHashValue(hPtr, kPtr->keysym); + } + KCHRPtr = (Ptr) GetScriptManagerVariable(smKCHRCache); + if (!KCHRPtr){ + fprintf(stderr,"GetScriptManagerVariable failed\n"); + } + initialized = 1; +} + +/* + *---------------------------------------------------------------------- + * + * XKeycodeToKeysym -- + * + * Translate from a system-dependent keycode to a + * system-independent keysym. + * + * Results: + * Returns the translated keysym, or NoSymbol on failure. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +KeySym +XKeycodeToKeysym( + Display* display, + KeyCode keycode, + int index) +{ + register Tcl_HashEntry *hPtr; + int c; + int virtualKey; + int newKeycode; + unsigned long dummy, newChar; + + if (!initialized) { + InitKeyMaps(); + } + virtualKey = (char) (keycode >> 16); + c = (keycode) & 0xffff; + if (c > 255) { + return NoSymbol; + } + + /* + * 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 ASCI chars. + */ + if (c == 0x10) { + hPtr = Tcl_FindHashEntry(&vkeyTable, (char *) virtualKey); + if (hPtr != NULL) { + return (KeySym) Tcl_GetHashValue(hPtr); + } + } + hPtr = Tcl_FindHashEntry(&keycodeTable, (char *) virtualKey); + if (hPtr != NULL) { + return (KeySym) Tcl_GetHashValue(hPtr); + } + + /* + * Recompute the character based on the Shift key only. + * TODO: The index may also specify the NUM_LOCK. + */ + newKeycode = virtualKey; + if (index & 0x01) { + newKeycode += 0x0200; + } + dummy = 0; + newChar = KeyTranslate(KCHRPtr, (short) newKeycode, &dummy); + c = newChar & charCodeMask; + + if (c >= XK_space && c < XK_asciitilde) { + return c; + } + + return NoSymbol; +} + +/* + *---------------------------------------------------------------------- + * + * TkpGetString -- + * + * Retrieve the string equivalent for the given keyboard event. + * + * Results: + * Returns the UTF string. + * + * Side effects: + * 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. */ +{ + register Tcl_HashEntry *hPtr; + char string[3]; + int virtualKey; + int c, len; + + if (!initialized) { + InitKeyMaps(); + } + + Tcl_DStringInit(dsPtr); + + virtualKey = (char) (eventPtr->xkey.keycode >> 16); + c = (eventPtr->xkey.keycode) & 0xffff; + + if (c < 256) { + string[0] = (char) c; + len = 1; + } else { + string[0] = (char) (c >> 8); + string[1] = (char) c; + len = 2; + } + /* + * Just return NULL if the character is a function key or another + * non-printing key. + */ + if (c == 0x10) { + len = 0; + } else { + hPtr = Tcl_FindHashEntry(&keycodeTable, (char *) virtualKey); + if (hPtr != NULL) { + len = 0; + } + } + return Tcl_ExternalToUtfDString(TkMacOSXCarbonEncoding, string, + len, dsPtr); +} + +/* + *---------------------------------------------------------------------- + * + * XGetModifierMapping -- + * + * Fetch the current keycodes used as modifiers. + * + * Results: + * Returns a new modifier map. + * + * Side effects: + * Allocates a new modifier map data structure. + * + *---------------------------------------------------------------------- + */ + +XModifierKeymap * +XGetModifierMapping( + Display* display) +{ + XModifierKeymap * modmap; + + modmap = (XModifierKeymap *) ckalloc(sizeof(XModifierKeymap)); + modmap->max_keypermod = 0; + modmap->modifiermap = NULL; + return modmap; +} + +/* + *---------------------------------------------------------------------- + * + * XFreeModifiermap -- + * + * Deallocate a modifier map that was created by + * XGetModifierMapping. + * + * Results: + * None. + * + * Side effects: + * Frees the datastructure referenced by modmap. + * + *---------------------------------------------------------------------- + */ + +void +XFreeModifiermap( + XModifierKeymap *modmap) +{ + if (modmap->modifiermap != NULL) { + ckfree((char *) modmap->modifiermap); + } + ckfree((char *) modmap); +} + +/* + *---------------------------------------------------------------------- + * + * XKeysymToString, XStringToKeysym -- + * + * These X window functions map Keysyms to strings & strings to + * keysyms. However, Tk already does this for the most common keysyms. + * Therefor, these functions only need to support keysyms that will be + * specific to the Macintosh. Currently, there are none. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +char * +XKeysymToString( + KeySym keysym) +{ + return NULL; +} + +KeySym +XStringToKeysym( + const char* string) +{ + return NoSymbol; +} + +/* + *---------------------------------------------------------------------- + * + * XKeysymToKeycode -- + * + * The function XKeysymToKeycode is only used by tkTest.c and + * currently only implementes the support for keys used in the + * Tk test suite. + * FIXME - This is no longer true. This function is now used in + * "event generate" so we really should make it work. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +KeyCode +XKeysymToKeycode( + Display* display, + KeySym keysym) +{ + KeyCode keycode = 0; + char virtualKeyCode = 0; + + 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); + } + + return keycode; +} + +/* + * When mapping from a keysym to a keycode, need + * information about the modifier state that should be used + * so that when they call XKeycodeToKeysym taking into + * account the xkey.state, they will get back the original + * keysym. + */ + +void +TkpSetKeycodeAndState(tkwin, keySym, eventPtr) + Tk_Window tkwin; + KeySym keySym; + XEvent *eventPtr; +{ + Display *display; + int state; + KeyCode keycode; + + display = Tk_Display(tkwin); + + if (keySym == NoSymbol) { + keycode = 0; + } else { + keycode = XKeysymToKeycode(display, keySym); + } + if (keycode != 0) { + for (state = 0; state < 4; state++) { + if (XKeycodeToKeysym(display, keycode, state) == keySym) { + if (state & 1) { + eventPtr->xkey.state |= ShiftMask; + } + if (state & 2) { + TkDisplay *dispPtr; + + dispPtr = ((TkWindow *) tkwin)->dispPtr; + eventPtr->xkey.state |= dispPtr->modeModMask; + } + break; + } + } + } + eventPtr->xkey.keycode = keycode; +} + +/* + *---------------------------------------------------------------------- + * + * TkpGetKeySym -- + * + * 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. + * + * Side effects: + * In the first call for a given display, keycode-to- + * KeySym maps get loaded. + * + *---------------------------------------------------------------------- + */ + +KeySym +TkpGetKeySym(dispPtr, eventPtr) + TkDisplay *dispPtr; /* Display in which to + * map keycode. */ + XEvent *eventPtr; /* Description of X event. */ +{ + KeySym sym; + int index; + + /* + * Refresh the mapping information if it's stale + */ + + if (dispPtr->bindInfoStale) { + TkpInitKeymapInfo(dispPtr); + } + + /* + * 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. + */ + + index = 0; + if (eventPtr->xkey.state & dispPtr->modeModMask) { + index = 2; + } + if ((eventPtr->xkey.state & ShiftMask) + || ((dispPtr->lockUsage != LU_IGNORE) + && (eventPtr->xkey.state & LockMask))) { + index += 1; + } + sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, index); + + /* + * Special handling: if the key was shifted because of Lock, but + * lock is only caps lock, not shift lock, and the shifted keysym + * isn't upper-case alphabetic, then switch back to the unshifted + * keysym. + */ + + if ((index & 1) && !(eventPtr->xkey.state & ShiftMask) + && (dispPtr->lockUsage == LU_CAPS)) { + if (!(((sym >= XK_A) && (sym <= XK_Z)) + || ((sym >= XK_Agrave) && (sym <= XK_Odiaeresis)) + || ((sym >= XK_Ooblique) && (sym <= XK_Thorn)))) { + index &= ~1; + sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, + index); + } + } + + /* + * Another bit of special handling: if this is a shifted key and there + * is no keysym defined, then use the keysym for the unshifted key. + */ + + if ((index & 1) && (sym == NoSymbol)) { + sym = XKeycodeToKeysym(dispPtr->display, eventPtr->xkey.keycode, + index & ~1); + } + return sym; +} + +/* + *-------------------------------------------------------------- + * + * 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 "mode + * switch". + * + * Results: + * None. + * + * Side effects: + * Keymap-related information in dispPtr is updated. + * + *-------------------------------------------------------------- + */ + +void +TkpInitKeymapInfo(dispPtr) + TkDisplay *dispPtr; /* Display for which to recompute keymap + * information. */ +{ + XModifierKeymap *modMapPtr; + KeyCode *codePtr; + KeySym keysym; + int count, i, j, max, arraySize; +#define KEYCODE_ARRAY_SIZE 20 + + dispPtr->bindInfoStale = 0; + modMapPtr = XGetModifierMapping(dispPtr->display); + + /* + * Check the keycodes associated with the Lock modifier. If + * any of them is associated with the XK_Shift_Lock modifier, + * then Lock has to be interpreted as Shift Lock, not Caps Lock. + */ + + dispPtr->lockUsage = LU_IGNORE; + codePtr = modMapPtr->modifiermap + modMapPtr->max_keypermod*LockMapIndex; + for (count = modMapPtr->max_keypermod; count > 0; count--, codePtr++) { + if (*codePtr == 0) { + continue; + } + keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0); + if (keysym == XK_Shift_Lock) { + dispPtr->lockUsage = LU_SHIFT; + break; + } + if (keysym == XK_Caps_Lock) { + dispPtr->lockUsage = LU_CAPS; + break; + } + } + + /* + * Look through the keycodes associated with modifiers to see if + * the the "mode switch", "meta", or "alt" keysyms are associated + * with any modifiers. If so, remember their modifier mask bits. + */ + + dispPtr->modeModMask = 0; + dispPtr->metaModMask = 0; + dispPtr->altModMask = 0; + codePtr = modMapPtr->modifiermap; + max = 8*modMapPtr->max_keypermod; + for (i = 0; i < max; i++, codePtr++) { + if (*codePtr == 0) { + continue; + } + keysym = XKeycodeToKeysym(dispPtr->display, *codePtr, 0); + if (keysym == XK_Mode_switch) { + dispPtr->modeModMask |= ShiftMask << (i/modMapPtr->max_keypermod); + } + if ((keysym == XK_Meta_L) || (keysym == XK_Meta_R)) { + dispPtr->metaModMask |= ShiftMask << (i/modMapPtr->max_keypermod); + } + if ((keysym == XK_Alt_L) || (keysym == XK_Alt_R)) { + dispPtr->altModMask |= ShiftMask << (i/modMapPtr->max_keypermod); + } + } + + /* + * Create an array of the keycodes for all modifier keys. + */ + + if (dispPtr->modKeyCodes != NULL) { + ckfree((char *) dispPtr->modKeyCodes); + } + dispPtr->numModKeyCodes = 0; + arraySize = KEYCODE_ARRAY_SIZE; + dispPtr->modKeyCodes = (KeyCode *) ckalloc((unsigned) + (KEYCODE_ARRAY_SIZE * sizeof(KeyCode))); + for (i = 0, codePtr = modMapPtr->modifiermap; i < max; i++, codePtr++) { + if (*codePtr == 0) { + continue; + } + + /* + * Make sure that the keycode isn't already in the array. + */ + + for (j = 0; j < dispPtr->numModKeyCodes; j++) { + if (dispPtr->modKeyCodes[j] == *codePtr) { + goto nextModCode; + } + } + if (dispPtr->numModKeyCodes >= arraySize) { + KeyCode *new; + + /* + * Ran out of space in the array; grow it. + */ + + arraySize *= 2; + new = (KeyCode *) ckalloc((unsigned) + (arraySize * sizeof(KeyCode))); + memcpy((VOID *) new, (VOID *) dispPtr->modKeyCodes, + (dispPtr->numModKeyCodes * sizeof(KeyCode))); + ckfree((char *) dispPtr->modKeyCodes); + dispPtr->modKeyCodes = new; + } + dispPtr->modKeyCodes[dispPtr->numModKeyCodes] = *codePtr; + dispPtr->numModKeyCodes++; + nextModCode: continue; + } + XFreeModifiermap(modMapPtr); +} diff --git a/macosx/tkMacOSXLibrary.r b/macosx/tkMacOSXLibrary.r new file mode 100644 index 0000000..4baf9b5 --- /dev/null +++ b/macosx/tkMacOSXLibrary.r @@ -0,0 +1,510 @@ +/* + * tkMacOSXLibrary.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. + * + * Copyright (c) 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: tkMacOSXLibrary.r,v 1.2 2002/08/31 06:12:30 das Exp $ + */ + +/* + * New style DLOG templates have an extra field for the positioning + * options for the Dialog Box. We will not use this, for now, so we + * turn it off here. + */ + +#define DLOG_RezTemplateVersion 0 + +/* +#include <Types.r> +#include <SysTypes.r> +#include <AEUserTermTypes.r> +*/ + +/* + * The folowing include and defines help construct + * the version string for Tcl. + */ + +#define RESOURCE_INCLUDED +#include <tcl.h> +#include "tk.h" + +#if (TK_RELEASE_LEVEL == 0) +# define RELEASE_LEVEL alpha +#elif (TK_RELEASE_LEVEL == 1) +# define RELEASE_LEVEL beta +#elif (TK_RELEASE_LEVEL == 2) +# define RELEASE_LEVEL final +#endif + +#if (TK_RELEASE_LEVEL == 2) +# define MINOR_VERSION (TK_MINOR_VERSION * 16) + TK_RELEASE_SERIAL +#else +# define MINOR_VERSION TK_MINOR_VERSION * 16 +#endif + +#define RELEASE_CODE 0x00 + +resource 'vers' (1) { + TK_MAJOR_VERSION, MINOR_VERSION, + RELEASE_LEVEL, 0x00, verUS, + TK_PATCH_LEVEL, + TK_PATCH_LEVEL ",by Ray Johnson & Jim Ingham" "\n" "© 1993-1997 Sun Microsystems" "\n" "1998-2000 Scriptics Inc." +}; + +resource 'vers' (2) { + TK_MAJOR_VERSION, MINOR_VERSION, + RELEASE_LEVEL, 0x00, verUS, + TK_PATCH_LEVEL, + "Tk Library " TK_PATCH_LEVEL " © 1993-1999" +}; + +#define TK_LIBRARY_RESOURCES 3000 +/* + * The -16397 string will be displayed by Finder when a user + * tries to open the shared library. The string should + * give the user a little detail about the library's capabilities + * and enough information to install the library in the correct location. + * A similar string should be placed in all shared libraries. + */ +resource 'STR ' (-16397, purgeable) { + "Tk Library\n\n" + "This is the library needed to run Tcl/Tk programs. " + "To work properly, it should be placed in the Tool Command Language folder " + "within the Extensions folder." +}; + + +/* + * We now load the Tk library into the resource fork of the library. + */ + +read 'TEXT' (TK_LIBRARY_RESOURCES+1, "tk", purgeable) + "::library:tk.tcl"; +read 'TEXT' (TK_LIBRARY_RESOURCES+2, "button", purgeable) + "::library:button.tcl"; +read 'TEXT' (TK_LIBRARY_RESOURCES+3, "dialog", purgeable) + "::library:dialog.tcl"; +read 'TEXT' (TK_LIBRARY_RESOURCES+4, "entry", purgeable) + "::library:entry.tcl"; +read 'TEXT' (TK_LIBRARY_RESOURCES+5, "focus", purgeable) + "::library:focus.tcl"; +read 'TEXT' (TK_LIBRARY_RESOURCES+6, "listbox", purgeable) + "::library:listbox.tcl"; +read 'TEXT' (TK_LIBRARY_RESOURCES+7, "menu", purgeable) + "::library:menu.tcl"; +read 'TEXT' (TK_LIBRARY_RESOURCES+8, "optionMenu", purgeable) + "::library:optMenu.tcl"; +read 'TEXT' (TK_LIBRARY_RESOURCES+9, "palette", purgeable) + "::library:palette.tcl"; +read 'TEXT' (TK_LIBRARY_RESOURCES+10, "scale", purgeable) + "::library:scale.tcl"; +read 'TEXT' (TK_LIBRARY_RESOURCES+11, "scrollbar", purgeable) + "::library:scrlbar.tcl"; +read 'TEXT' (TK_LIBRARY_RESOURCES+12, "tearoff", purgeable) + "::library:tearoff.tcl"; +read 'TEXT' (TK_LIBRARY_RESOURCES+13, "text", purgeable) + "::library:text.tcl"; +read 'TEXT' (TK_LIBRARY_RESOURCES+14, "tkerror", purgeable) + "::library:bgerror.tcl"; +read 'TEXT' (TK_LIBRARY_RESOURCES+15, "Console", purgeable) + "::library:console.tcl"; +read 'TEXT' (TK_LIBRARY_RESOURCES+16, "msgbox", purgeable, preload) + "::library:msgbox.tcl"; +read 'TEXT' (TK_LIBRARY_RESOURCES+17, "comdlg", purgeable, preload) + "::library:comdlg.tcl"; + +/* + * 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 + * default dialog will not be shown and the Tcl procedure is expected to + * create and manage an About Dialog box. + */ + +data 'DLOG' (128, "Default About Box", purgeable) { + $"0055 006B 00F3 0196 0001 0100 0100 0000" + $"0000 0081 0000 280A" +}; + +resource 'DITL' (129, "About Box", purgeable) { + { + {128, 128, 148, 186}, Button {enabled, "Ok"}, + { 14, 108, 117, 298}, StaticText {disabled, + "Wish - Windowing Shell" "\n" "based on Tcl " + TCL_PATCH_LEVEL " & Tk " TK_PATCH_LEVEL "\n\n" "Jim Ingham & Ray Johnson" + "Scriptics Inc." "\n" "jingham@cygnus.com"}, + { 11, 24, 111, 92}, Picture {enabled, 128} + } +}; + +data 'PICT' (128, purgeable) { + $"13A4 0000 0000 0064 0044 0011 02FF 0C00" + $"FFFE 0000 0048 0000 0048 0000 0000 0000" + $"0064 0044 0000 0000 0001 000A 0000 0000" + $"0064 0044 0099 8044 0000 0000 0064 0044" + $"0000 0000 0000 0000 0048 0000 0048 0000" + $"0000 0008 0001 0008 0000 0000 0108 00D8" + $"0000 0000 0001 5A5A 8000 00FF 3736 FF00" + $"FF00 FF00 3535 FF00 FF00 CC00 3434 FF00" + $"FF00 9900 3333 FF00 FF00 6600 3736 FF00" + $"FF00 3300 3535 FF00 FF00 0000 3434 FF00" + $"CC00 FF00 3333 FF00 CC00 CC00 3736 FF00" + $"CC00 9900 3535 FF00 CC00 6600 FAFA FF00" + $"CC00 3300 3333 FF00 CC00 0000 3130 FF00" + $"9900 FF00 2F2F FF00 9900 CC00 FAFA FF00" + $"9900 9900 F9F9 FF00 9900 6600 3130 FF00" + $"9900 3300 2F2F FF00 9900 0000 2E2E FF00" + $"6600 FF00 F9F9 FF00 6600 CC00 3130 FF00" + $"6600 9900 2F2F FF00 6600 6600 2E2E FF00" + $"6600 3300 2D2D FF00 6600 0000 3130 FF00" + $"3300 FF00 2F2F FF00 3300 CC00 2E2E FF00" + $"3300 9900 2D2D FF00 3300 6600 3130 FF00" + $"3300 3300 2F2F FF00 3300 0000 2E2E FF00" + $"0000 FF00 2D2D FF00 0000 CC00 3130 FF00" + $"0000 9900 2F2F FF00 0000 6600 2E2E FF00" + $"0000 3300 2DF8 FF00 0000 0000 2B2A CC00" + $"FF00 FF00 2929 CC00 FF00 CC00 2828 CC00" + $"FF00 9900 27F8 CC00 FF00 6600 2B2A CC00" + $"FF00 3300 2929 CC00 FF00 0000 2828 CC00" + $"CC00 FF00 2727 CC00 CC00 CC00 2B2A CC00" + $"CC00 9900 2929 CC00 CC00 6600 2828 CC00" + $"CC00 3300 2727 CC00 CC00 0000 2B2A CC00" + $"9900 FF00 2929 CC00 9900 CC00 2828 CC00" + $"9900 9900 2727 CC00 9900 6600 DBDB CC00" + $"9900 3300 4747 CC00 9900 0000 4646 CC00" + $"6600 FF00 4545 CC00 6600 CC00 DBDB CC00" + $"6600 9900 4747 CC00 6600 6600 4646 CC00" + $"6600 3300 4545 CC00 6600 0000 DBDB CC00" + $"3300 FF00 4747 CC00 3300 CC00 4646 CC00" + $"3300 9900 4545 CC00 3300 6600 DBDB CC00" + $"3300 3300 4141 CC00 3300 0000 4040 CC00" + $"0000 FF00 3F3F CC00 0000 CC00 4342 CC00" + $"0000 9900 4141 CC00 0000 6600 4040 CC00" + $"0000 3300 3F3F CC00 0000 0000 4342 9900" + $"FF00 FF00 4141 9900 FF00 CC00 4040 9900" + $"FF00 9900 3F3F 9900 FF00 6600 4342 9900" + $"FF00 3300 4141 9900 FF00 0000 4040 9900" + $"CC00 FF00 3F3F 9900 CC00 CC00 4342 9900" + $"CC00 9900 4141 9900 CC00 6600 4040 9900" + $"CC00 3300 3F3F 9900 CC00 0000 4342 9900" + $"9900 FF00 4141 9900 9900 CC00 4040 9900" + $"9900 9900 3F3F 9900 9900 6600 3D3C 9900" + $"9900 3300 3B3B 9900 9900 0000 3A3A 9900" + $"6600 FF00 3939 9900 6600 CC00 3D3C 9900" + $"6600 9900 3B3B 9900 6600 6600 3A3A 9900" + $"6600 3300 3939 9900 6600 0000 3D3C 9900" + $"3300 FF00 3B3B 9900 3300 CC00 3A3A 9900" + $"3300 9900 3939 9900 3300 6600 3D3C 9900" + $"3300 3300 3B3B 9900 3300 0000 3A3A 9900" + $"0000 FF00 3939 9900 0000 CC00 3D3C 9900" + $"0000 9900 3B3B 9900 0000 6600 3A3A 9900" + $"0000 3300 3939 9900 0000 0000 3D3C 6600" + $"FF00 FF00 3B3B 6600 FF00 CC00 3A3A 6600" + $"FF00 9900 3939 6600 FF00 6600 3D3C 6600" + $"FF00 3300 3B3B 6600 FF00 0000 3A3A 6600" + $"CC00 FF00 3939 6600 CC00 CC00 3736 6600" + $"CC00 9900 3535 6600 CC00 6600 3434 6600" + $"CC00 3300 3333 6600 CC00 0000 3736 6600" + $"9900 FF00 3535 6600 9900 CC00 3434 6600" + $"9900 9900 3333 6600 9900 6600 3736 6600" + $"9900 3300 3535 6600 9900 0000 3434 6600" + $"6600 FF00 3333 6600 6600 CC00 3736 6600" + $"6600 9900 3535 6600 6600 6600 3434 6600" + $"6600 3300 3333 6600 6600 0000 3736 6600" + $"3300 FF00 3535 6600 3300 CC00 3434 6600" + $"3300 9900 3333 6600 3300 6600 3736 6600" + $"3300 3300 3535 6600 3300 0000 3434 6600" + $"0000 FF00 3333 6600 0000 CC00 3130 6600" + $"0000 9900 2F2F 6600 0000 6600 2E2E 6600" + $"0000 3300 F9F9 6600 0000 0000 3130 3300" + $"FF00 FF00 2F2F 3300 FF00 CC00 2E2E 3300" + $"FF00 9900 F9F9 3300 FF00 6600 3130 3300" + $"FF00 3300 2F2F 3300 FF00 0000 2E2E 3300" + $"CC00 FF00 2D2D 3300 CC00 CC00 3130 3300" + $"CC00 9900 2F2F 3300 CC00 6600 2E2E 3300" + $"CC00 3300 2D2D 3300 CC00 0000 3130 3300" + $"9900 FF00 2F2F 3300 9900 CC00 2E2E 3300" + $"9900 9900 2D2D 3300 9900 6600 3130 3300" + $"9900 3300 2F2F 3300 9900 0000 2E2E 3300" + $"6600 FF00 2DF8 3300 6600 CC00 2B2A 3300" + $"6600 9900 2929 3300 6600 6600 2828 3300" + $"6600 3300 27F8 3300 6600 0000 2B2A 3300" + $"3300 FF00 2929 3300 3300 CC00 2828 3300" + $"3300 9900 2727 3300 3300 6600 2B2A 3300" + $"3300 3300 2929 3300 3300 0000 2828 3300" + $"0000 FF00 2727 3300 0000 CC00 2B2A 3300" + $"0000 9900 2929 3300 0000 6600 2828 3300" + $"0000 3300 2727 3300 0000 0000 4948 0000" + $"FF00 FF00 4747 0000 FF00 CC00 4646 0000" + $"FF00 9900 4545 0000 FF00 6600 4948 0000" + $"FF00 3300 4747 0000 FF00 0000 4646 0000" + $"CC00 FF00 4545 0000 CC00 CC00 4948 0000" + $"CC00 9900 4747 0000 CC00 6600 4646 0000" + $"CC00 3300 4545 0000 CC00 0000 4342 0000" + $"9900 FF00 4141 0000 9900 CC00 4040 0000" + $"9900 9900 3F3F 0000 9900 6600 4342 0000" + $"9900 3300 4141 0000 9900 0000 4040 0000" + $"6600 FF00 3F3F 0000 6600 CC00 4342 0000" + $"6600 9900 4141 0000 6600 6600 4040 0000" + $"6600 3300 3F3F 0000 6600 0000 4342 0000" + $"3300 FF00 4141 0000 3300 CC00 4040 0000" + $"3300 9900 3F3F 0000 3300 6600 4342 0000" + $"3300 3300 4141 0000 3300 0000 4040 0000" + $"0000 FF00 3F3F 0000 0000 CC00 4342 0000" + $"0000 9900 4141 0000 0000 6600 4040 0000" + $"0000 3300 3F3F EE00 0000 0000 3D3C DD00" + $"0000 0000 3B3B BB00 0000 0000 3A3A AA00" + $"0000 0000 3939 8800 0000 0000 3D3C 7700" + $"0000 0000 3B3B 5500 0000 0000 3A3A 4400" + $"0000 0000 3939 2200 0000 0000 3D3C 1100" + $"0000 0000 3B3B 0000 EE00 0000 3A3A 0000" + $"DD00 0000 3939 0000 BB00 0000 3D3C 0000" + $"AA00 0000 3B3B 0000 8800 0000 3A3A 0000" + $"7700 0000 3939 0000 5500 0000 3D3C 0000" + $"4400 0000 3B3B 0000 2200 0000 3A3A 0000" + $"1100 0000 3939 0000 0000 EE00 3D3C 0000" + $"0000 DD00 3B3B 0000 0000 BB00 3A3A 0000" + $"0000 AA00 3939 0000 0000 8800 3D3C 0000" + $"0000 7700 3B3B 0000 0000 5500 3A3A 0000" + $"0000 4400 3939 0000 0000 2200 3736 0000" + $"0000 1100 3535 EE00 EE00 EE00 3434 DD00" + $"DD00 DD00 3333 BB00 BB00 BB00 3736 AA00" + $"AA00 AA00 3535 8800 8800 8800 3434 7700" + $"7700 7700 3333 5500 5500 5500 3736 4400" + $"4400 4400 3535 2200 2200 2200 3434 1100" + $"1100 1100 3333 0000 0000 0000 0000 0000" + $"0064 0044 0000 0000 0064 0044 0000 000A" + $"0000 0000 0064 0044 02BD 0013 E800 01F5" + $"F6FE 07FE 0E02 3232 33FD 3900 0EE6 001D" + $"FC00 01F5 F5FE 0700 08FE 0E02 3232 33FE" + $"3900 3AFC 40F2 4102 4033 07E9 0017 0100" + $"0EFC 40DC 4102 390E F5F5 0002 F5F5 F6FE" + $"0702 0E07 0016 0100 32D5 4104 4039 0E32" + $"33FD 3900 3AFC 40FC 4101 3200 0801 000E" + $"C141 010E 0008 0100 0EC1 4101 0800 0801" + $"000E C141 0107 0008 0100 0EC1 4101 0700" + $"0901 0007 C241 0240 F500 0E01 0007 E841" + $"0147 47DD 4102 4000 0012 0100 07F0 4100" + $"47FA 4101 3B3B DD41 0240 0000 1901 0007" + $"F141 0C47 3B0B 3B47 4141 4711 0505 3B47" + $"DF41 023A 0000 1701 00F6 F041 010B 0BFE" + $"4105 473B 0505 113B DE41 0239 0000 1A02" + $"00F5 40F3 410C 473B 053B 4741 4741 0B0B" + $"3B47 47DE 4102 3900 0018 0200 F540 F341" + $"0247 110B FE41 0447 1105 4147 DC41 0233" + $"0000 1B02 0000 40F3 4103 4711 1147 FE41" + $"0205 3547 F741 FD47 E941 0232 0000 1E02" + $"0000 40F2 4106 113B 4741 4735 0BF7 4106" + $"4741 390E 0E40 47EA 4102 0E00 0021 0200" + $"0040 F241 0711 3B47 4141 0B35 47F9 4102" + $"4740 07FE 0002 F640 47EB 4102 0E00 0023" + $"0200 0040 F341 0847 3541 4147 3B05 4147" + $"FA41 0947 3AF6 00F5 4F55 F50E 47EB 4102" + $"0700 0022 0200 003A F341 0147 3BFE 4101" + $"0B0B F941 0547 3AF5 0055 C8FE CE01 5640" + $"EB41 0207 0000 1F02 0000 39F0 4104 4741" + $"053B 47FB 4104 4740 F5F5 A4FC CE01 C85D" + $"EB41 02F6 0000 1F02 0000 39F0 4104 473B" + $"0541 47FC 4104 4740 07F6 C8FA CE00 64EC" + $"4103 40F5 0000 1C02 0000 39F0 4102 4711" + $"0BFA 4103 4708 2AC8 FACE 0164 D8EC 4100" + $"40FE 0025 0200 0039 EF41 020B 3B47 FC41" + $"0347 0FF5 A4FB CE02 C887 D8FC 41FE 47FC" + $"4100 47F9 4100 3AFE 0028 0200 0039 EF41" + $"020B 3B47 FD41 0347 3900 A4FA CE00 ABFA" + $"4109 3B11 3B41 4147 3B0B 3B47 FA41 0039" + $"FE00 2402 0000 33F1 4102 4741 0BFA 4101" + $"0779 F9CE 0064 FA41 0235 050B FD41 010B" + $"0BF9 4100 39FE 0028 0200 0032 F141 0247" + $"3B0B FC41 0247 39F6 F9CE 0187 D8FB 4103" + $"4741 050B FE41 0247 110B F941 0039 FE00" + $"2C02 0000 32F1 4102 473B 11FB 4101 0879" + $"FACE 05AA 4041 4147 47FE 410A 4741 0511" + $"4741 4147 3511 47FA 4100 32FE 002F 0200" + $"000E F141 0347 3B11 47FE 4103 4740 F6C8" + $"FACE 0564 D841 4039 39FE 4104 473B 053B" + $"47FE 4102 3541 47FA 4100 0EFE 0027 0200" + $"000E F141 0347 3B3B 47FE 4102 470F 79FA" + $"CE0C 8741 4032 F500 003A 4741 473B 05F2" + $"4100 0EFE 0027 0200 000E F141 0347 3B3B" + $"47FD 4101 0EA4 FACE 01AB AAFE C808 7900" + $"3947 4147 110B 47F3 4100 07FE 001C 0200" + $"000E EA41 0240 2BC8 F5CE 0881 0033 4741" + $"410B 3B47 F341 0007 FE00 1A02 0000 08EB" + $"4102 473A 55F4 CE06 5D00 3947 4741 0BF1" + $"4100 F6FE 001C 0200 0007 EB41 0247 3979" + $"F4CE 0739 0039 4747 3511 47F3 4101 40F5" + $"FE00 1C02 0000 07EB 4102 4739 A4F5 CE08" + $"AB0E 0040 4741 1141 47F3 4100 40FD 001B" + $"0200 0007 EB41 0247 39A4 F5CE 0787 0707" + $"4147 4111 47F2 4100 40FD 001B 0200 0007" + $"EB41 0247 39C8 F5CE 0763 F532 4747 3B3B" + $"47F2 4100 3AFD 001A 0300 00F6 40EC 4102" + $"4739 C8F5 CE05 39F5 4047 413B F041 0039" + $"FD00 1C03 0000 F540 EB41 0140 C8FD CE01" + $"C8A4 FCCE 03AB 080E 47ED 4100 39FD 001A" + $"FE00 0040 EB41 0040 FCCE 01A4 C8FC CE03" + $"FA07 4047 ED41 0032 FD00 1AFE 0000 40EA" + $"4100 AAFE CE02 87F9 C8FC CE02 560F 47EC" + $"4100 32FD 0019 FE00 0040 EA41 00AB FECE" + $"0264 56C8 FDCE 01C8 32EA 4100 0EFD 001B" + $"FE00 0040 ED41 030E 4047 87FE CE01 4055" + $"FCCE 01FA 40EA 4100 08FD 001A FE00 003A" + $"ED41 0807 0740 FBCE CEAB 3979 FDCE 00AB" + $"E841 0007 FD00 1CFE 0000 3AED 4108 0700" + $"F6A4 CECE 8733 79FD CE02 4147 47EA 4100" + $"07FD 001E FE00 0039 ED41 0807 2AA4 C8CE" + $"CE88 0E9D FECE 0364 1C39 39EB 4101 40F5" + $"FD00 1CFE 0000 39ED 4101 074F FDCE 0264" + $"F7A4 FECE 03AB 80F6 07EB 4100 40FC 001C" + $"FE00 0039 ED41 0108 79FE CE03 AB40 2BA4" + $"FCCE 02F7 0E47 EC41 0040 FC00 1CFE 0000" + $"39ED 4101 0879 FECE 03AB 40F6 C8FC CE02" + $"F615 47EC 4100 40FC 001E FE00 003A EE41" + $"0247 0E79 FECE 03AB 40F5 C8FD CE03 A4F5" + $"3A47 EC41 0040 FC00 1EFE 0000 3AEE 4102" + $"470E 56FE CE03 FB3A F6C8 FDCE 0280 F540" + $"EB41 0140 F5FD 001E FE00 0040 EE41 0947" + $"0F56 CECE C888 39F6 C8FD CE02 5601 40EB" + $"4101 40F5 FD00 1CFE 0000 40EE 4109 4739" + $"32CE CEC8 8839 2AC8 FDCE 0156 07E9 4100" + $"F6FD 001B FE00 0040 EE41 0847 3A32 CECE" + $"C864 152A FCCE 0132 07E9 4100 07FD 001A" + $"FE00 0040 ED41 0740 32AB CEC8 6439 4EFC" + $"CE01 3A07 E941 0007 FD00 1D03 0000 F540" + $"ED41 0740 0EAB CECE 640F 4EFD CE03 AB40" + $"0840 EA41 0007 FD00 1B03 0000 F540 EC41" + $"060F 81CE CE64 334E FDCE 02AB 400E E941" + $"000E FD00 1C02 0000 F6EC 4107 4715 FACE" + $"CE64 334E FDCE 0387 0F0E 47EA 4100 0EFD" + $"001C 0200 0007 EC41 0747 16F9 CEC8 6433" + $"4EFD CE03 6308 4047 EA41 000E FD00 1A02" + $"0000 07EB 4106 40F9 CEC8 6439 4EFD CE02" + $"3940 47E9 4100 32FD 001B 0200 0007 EA41" + $"0539 CECE 8839 F6FE CE04 AB41 4139 40EA" + $"4100 32FD 001C 0200 0007 EB41 0E47 3AC8" + $"CE88 39F6 C8CE CE64 15F6 F540 EA41 0033" + $"FD00 1A02 0000 07EA 410C 40A4 CE87 392A" + $"C8CE AB41 40F8 F6E9 4100 39FD 001B 0200" + $"000E EB41 0D47 41AB C887 39F5 C8CE ABAB" + $"CEA4 07E9 4100 39FD 001C 0200 000E ED41" + $"0947 3939 4787 C8AB 40F5 C8FD CE01 A40E" + $"E941 0039 FD00 1D02 0000 0EED 4109 473A" + $"0007 80CE AB40 F5C8 FDCE 0255 0E47 EA41" + $"0039 FD00 1B02 0000 0EEB 4107 0779 C8CE" + $"CE40 F6A4 FDCE 022B 3947 EA41 003A FD00" + $"1C02 0000 0EEC 4102 4739 79FE CE02 6407" + $"A4FE CE02 A407 40E9 4100 40FD 001A 0200" + $"0032 EA41 0632 A4CE CE88 0879 FECE 02F9" + $"0F47 E941 0040 FD00 1A02 0000 32EB 4107" + $"4740 F7C8 CE87 0E79 FECE 0132 40E8 4100" + $"40FD 0019 0200 0033 EA41 0B47 40F8 C8AB" + $"0E55 CECE 8015 47E8 4100 40FD 0017 0200" + $"0033 E941 0847 40F9 A439 4FCE CE5D E641" + $"0140 F5FE 0014 0200 0039 E841 0647 64FB" + $"392B C8AB E441 00F6 FE00 1102 0000 39E5" + $"4103 40F6 8764 E441 0007 FE00 1E02 0000" + $"39EB 4102 3A0E 0EFD 4102 0740 47F6 4104" + $"400F 0839 47F4 4100 07FE 0027 0200 0039" + $"FB41 0147 47F2 4102 0800 40FE 4102 0839" + $"47FC 4101 4747 FC41 0339 0039 47F4 4100" + $"07FE 0029 0200 0039 FB41 0140 39F3 4109" + $"470E F540 4141 470E 3347 FC41 0139 3AFD" + $"4104 4739 0039 47F4 4100 08FE 0036 0200" + $"003A FC41 0347 0E00 40FC 4102 4741 40FC" + $"4109 470E F540 4141 4733 0E47 FE41 0447" + $"4000 0E47 FE41 0447 3900 3941 FE40 F741" + $"000E FE00 3A02 0000 3AFD 410E 4740 0700" + $"0E40 4741 4147 390E 390E 40FE 4108 470E" + $"F540 4141 4739 0EFC 4103 0F00 0739 FE41" + $"0747 3900 3940 080F 39F7 4100 0EFE 0035" + $"0200 0040 FB41 020E 0040 FE41 0D47 4000" + $"3941 0032 4741 4147 0EF5 40FE 4101 4008" + $"FC41 023A 000E FD41 0547 3900 3939 33F5" + $"4100 0EFE 0039 0200 0040 FC41 0347 0E00" + $"40FE 4106 4732 0040 4139 40FE 4103 470E" + $"F540 FD41 0108 40FE 4104 4740 000E 47FE" + $"4106 4739 0007 F540 47F6 4100 32FE 003A" + $"0200 0040 FC41 0C47 0E00 4047 4141 470E" + $"0040 4747 FD41 0347 0EF5 40FE 410A 470E" + $"3947 4141 4740 000E 47FE 4107 4739 000E" + $"0007 4147 F741 0032 FE00 3802 0000 40FC" + $"4102 470E 00FD 4106 4739 003A 4740 39FE" + $"4102 470E F5FD 410A 4733 3347 4141 4740" + $"000E 47FE 4106 4739 0039 3900 0EF6 4100" + $"33FE 003A 0200 F540 FC41 0447 3200 0E39" + $"FD41 0B0E 0E40 333A 4741 413A 07F5 39FE" + $"4102 473A 0EFD 410F 40F5 0733 4041 4140" + $"0E00 0E40 0700 0E40 F841 0039 FE00 2902" + $"00F5 40FA 4101 3939 FB41 023A 3A40 FD41" + $"FD40 FD41 0240 0E40 FD41 0240 3940 FD41" + $"FA40 F741 0039 FE00 2A01 00F6 F941 0147" + $"47FB 4101 4747 FB41 0147 47FB 4101 3940" + $"FD41 0147 47FB 4100 47FE 4100 47F6 4100" + $"39FE 000D 0100 07E1 4100 40E4 4100 3AFE" + $"0009 0100 07C3 4100 3AFE 0009 0100 07C3" + $"4100 40FE 0009 0100 07C3 4100 40FE 0009" + $"0100 07C3 4100 40FE 000A 0100 0EC3 4103" + $"40F5 0000 0901 000E C241 02F6 0000 0901" + $"000E C241 0207 0000 0901 000E C241 0207" + $"0000 1101 000E ED41 FE40 003A F940 E241" + $"0207 0000 2B01 0032 F941 FE40 FE39 0632" + $"0E0E 0707 F6F5 F800 02F5 F5F6 FB07 FB0E" + $"0332 3233 33FB 3901 3A3A FB40 0207 0000" + $"0E0A 000E 3939 320E 0E07 07F6 F5C8 0002" + $"BD00 00FF" +}; + +/* + * Here is the custom file open dialog. This dialog is used instead of + * the default file dialog if the -filetypes flag is specified. + */ + +#define DLOG_RezTemplateVersion 0 + +resource 'DLOG' (130, purgeable) { + {0, 0, 195, 344}, dBoxProc, invisible, noGoAway, 0, + 130, "" +}; + +resource 'DITL' (130, "File Open Box", purgeable) { + { + {135, 252, 155, 332}, Button {enabled, "Open"}, + {104, 252, 124, 332}, Button {enabled, "Cancel"}, + { 0, 0, 0, 0}, HelpItem {disabled, HMScanhdlg {130}}, + { 8, 235, 24, 337}, UserItem {enabled}, + { 32, 252, 52, 332}, Button {enabled, "Eject"}, + { 60, 252, 80, 332}, Button {enabled, "Desktop"}, + { 29, 12, 159, 230}, UserItem {enabled}, + { 6, 12, 25, 230}, UserItem {enabled}, + { 91, 251, 92, 333}, Picture {disabled, 11}, + {168, 20, 187, 300}, Control {enabled, 131} + } +}; + +resource 'CNTL' (131, "File Types menu", purgeable) { + {168, 20, 187, 300}, + popupTitleLeftJust, + visible, + 80, + 132, + popupMenuCDEFProc, + 0, + "File Type:" +}; + + +resource 'MENU' (132, preload) { + 132, + textMenuProc, + 0xFFFF, enabled, "", {} +}; diff --git a/macosx/tkMacOSXMenu.c b/macosx/tkMacOSXMenu.c new file mode 100644 index 0000000..8578359 --- /dev/null +++ b/macosx/tkMacOSXMenu.c @@ -0,0 +1,4686 @@ +/* + * tkMacOSXMenu.c -- + * + * This module implements the Mac-platform specific features of menus. + * + * Copyright (c) 1996-1997 by Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkMacOSXMenu.c,v 1.2 2002/08/31 06:12:30 das Exp $ + */ +#include "tkMacOSXInt.h" +#include "tkMenuButton.h" +#include "tkMenu.h" +#include "tkColor.h" +#include "tkMacOSXInt.h" +#undef Status + +#define USE_TK_MDEF +//#define USE_ATSU + +#include <Carbon/Carbon.h> +#include "tkMacOSXDebug.h" +#include <CoreFoundation/CFString.h> + +typedef struct MacMenu { + MenuRef menuHdl; /* The Menu Manager data structure. */ + Rect menuRect; /* The rectangle as calculated in the + * MDEF. This is used to figure ou the + * clipping rgn before we push + * the <<MenuSelect>> virtual binding + * through. */ +} MacMenu; + +typedef struct MenuEntryUserData { + Drawable mdefDrawable; + TkMenuEntry *mePtr; + Tk_Font tkfont; + Tk_FontMetrics *fmPtr; +} MenuEntryUserData; +/* + * Various geometry definitions: + */ + +#define CASCADE_ARROW_HEIGHT 10 +#define CASCADE_ARROW_WIDTH 8 +#define DECORATION_BORDER_WIDTH 2 +#define MAC_MARGIN_WIDTH 8 + +/* + * The following are constants relating to the SICNs used for drawing the MDEF. + */ + +#define SICN_RESOURCE_NUMBER 128 + +#define SICN_HEIGHT 16 +#define SICN_ROWS 2 +#define CASCADE_ICON_WIDTH 7 +#define SHIFT_ICON_WIDTH 10 +#define OPTION_ICON_WIDTH 16 +#define CONTROL_ICON_WIDTH 12 +#define COMMAND_ICON_WIDTH 10 + +#define CASCADE_ARROW 0 +#define SHIFT_ICON 1 +#define OPTION_ICON 2 +#define CONTROL_ICON 3 +#define COMMAND_ICON 4 +#define DOWN_ARROW 5 +#define UP_ARROW 6 + +/* + * Platform specific flags for menu entries + * + * ENTRY_COMMAND_ACCEL Indicates the entry has the command key + * in its accelerator string. + * ENTRY_OPTION_ACCEL Indicates the entry has the option key + * in its accelerator string. + * ENTRY_SHIFT_ACCEL Indicates the entry has the shift key + * in its accelerator string. + * ENTRY_CONTROL_ACCEL Indicates the entry has the control key + * in its accelerator string. + */ + +#define ENTRY_COMMAND_ACCEL ENTRY_PLATFORM_FLAG1 +#define ENTRY_OPTION_ACCEL ENTRY_PLATFORM_FLAG2 +#define ENTRY_SHIFT_ACCEL ENTRY_PLATFORM_FLAG3 +#define ENTRY_CONTROL_ACCEL ENTRY_PLATFORM_FLAG4 +#define ENTRY_ACCEL_MASK (ENTRY_COMMAND_ACCEL | ENTRY_OPTION_ACCEL \ + | ENTRY_SHIFT_ACCEL | ENTRY_CONTROL_ACCEL) + +/* + * This structure is used to keep track of subfields within Macintosh menu + * items. + */ + +typedef struct EntryGeometry { + int accelTextStart; /* Offset into the accel string where + * the text starts. Everything before + * this is modifier key descriptions. + */ + int modifierWidth; /* Width of modifier symbols. */ + int accelTextWidth; /* Width of the text after the modifier + * keys. */ + int nonAccelMargin; /* The width of the margin for entries + * without accelerators. */ +} EntryGeometry; + +/* + * Structure to keep track of toplevel windows and their menubars. + */ + +typedef struct TopLevelMenubarList { + struct TopLevelMenubarList *nextPtr; + /* The next window in the list. */ + Tk_Window tkwin; /* The toplevel window. */ + TkMenu *menuPtr; /* The menu associated with this + * toplevel. */ +} TopLevelMenubarList; + +/* + * Platform-specific flags for menus. + * + * MENU_APPLE_MENU 0 indicates a custom Apple menu has + * not been installed; 1 a custom Apple + * menu has been installed. + * MENU_HELP_MENU 0 indicates a custom Help menu has + * not been installed; 1 a custom Help + * menu has been installed. + * MENU_RECONFIGURE_PENDING 1 indicates that an idle handler has + * been scheduled to reconfigure the + * Macintosh MenuHandle. + */ + +#define MENU_APPLE_MENU MENU_PLATFORM_FLAG1 +#define MENU_HELP_MENU MENU_PLATFORM_FLAG2 +#define MENU_RECONFIGURE_PENDING MENU_PLATFORM_FLAG3 + +#define CASCADE_CMD (0x1b) + /* The special command char for cascade + * menus. */ +#define SEPARATOR_TEXT "\p(-" + /* The text for a menu separator. */ + +#define MENUBAR_REDRAW_PENDING 1 +#define SCREEN_MARGIN 5 + +static int gNoTkMenus = 0; /* This is used by Tk_MacOSXTurnOffMenus as the + * flag that Tk is not to draw any menus. */ + +RgnHandle tkMenuCascadeRgn = NULL; + /* The region to clip drawing to when the + * MDEF is up. */ +int tkUseMenuCascadeRgn = 0; /* 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. */ + +static Tcl_HashTable commandTable; + /* The list of menuInstancePtrs associated with + * menu ids */ +static short currentAppleMenuID; + /* The id of the current Apple menu. 0 for + * none. */ +static short currentHelpMenuID; /* The id of the current Help menu. 0 for + * none. */ +static Tcl_Interp *currentMenuBarInterp; + /* The interpreter of the window that owns + * the current menubar. */ +static char *currentMenuBarName; + /* Malloced. Name of current menu in menu bar. + * NULL if no menu set. TO DO: make this a + * DString. */ +static Tk_Window currentMenuBarOwner; + /* Which window owns the current menu bar. */ +static char elipsisString[TCL_UTF_MAX + 1]; + /* The UTF representation of the elipsis (...) + * character. */ +static int helpItemCount; /* The number of items in the help menu. + * -1 means that the help menu is + * unavailable. This does not include + * the automatically generated separator. */ +static int inPostMenu; /* We cannot be re-entrant like X + * windows. */ +static short lastMenuID; /* To pass to NewMenu; need to figure out + * a good way to do this. */ +static unsigned char lastCascadeID; + /* Cascades have to have ids that are + * less than 256. */ +static MacDrawable macMDEFDrawable; + /* Drawable for use by MDEF code */ +static int MDEFScrollFlag = 0; /* Used so that popups don't scroll too soon. */ +static int menuBarFlags; /* Used for whether the menu bar needs + * redrawing or not. */ + +static struct TearoffSelect { + TkMenu *menuPtr; /* The menu that is torn off */ + Point point; /* The point to place the new menu */ + Rect excludeRect; /* We don't want to drag tearoff highlights + * when we are in this menu */ +} tearoffStruct; + +static RgnHandle totalMenuRgn = NULL; + /* Used to update windows which have been + * obscured by menus. */ +static RgnHandle utilRgn = NULL;/* Used when creating the region that is to + * be clipped out while the MDEF is active. */ + +static TopLevelMenubarList *windowListPtr; + /* A list of windows that have menubars set. */ +static MenuItemDrawingUPP tkThemeMenuItemDrawingUPP; + /* Points to the UPP for theme Item drawing. */ +static Tcl_Obj *useMDEFVar; + +/* + * Forward declarations for procedures defined later in this file: + */ + +int TkMacOSXGetNewMenuID _ANSI_ARGS_((Tcl_Interp *interp, + TkMenu *menuInstPtr, + int cascade, + short *menuIDPtr)); +void TkMacOSXFreeMenuID _ANSI_ARGS_((short menuID)); + +static void CompleteIdlers _ANSI_ARGS_((TkMenu *menuPtr)); +static void DrawMenuBarWhenIdle _ANSI_ARGS_(( + ClientData clientData)); +static void DrawMenuBackground _ANSI_ARGS_(( + Rect *menuRectPtr, Drawable d, ThemeMenuType type)); +static void DrawMenuEntryAccelerator _ANSI_ARGS_(( + TkMenu *menuPtr, TkMenuEntry *mePtr, + Drawable d, GC gc, Tk_Font tkfont, + CONST Tk_FontMetrics *fmPtr, + Tk_3DBorder activeBorder, int x, int y, + int width, int height, int drawArrow)); +static void DrawMenuEntryBackground _ANSI_ARGS_(( + TkMenu *menuPtr, TkMenuEntry *mePtr, + Drawable d, Tk_3DBorder activeBorder, + Tk_3DBorder bgBorder, int x, int y, + int width, int heigth)); +static void DrawMenuEntryIndicator _ANSI_ARGS_(( + TkMenu *menuPtr, TkMenuEntry *mePtr, + Drawable d, GC gc, GC indicatorGC, + Tk_Font tkfont, + CONST Tk_FontMetrics *fmPtr, int x, int y, + int width, int height)); +static void DrawMenuEntryLabel _ANSI_ARGS_(( + TkMenu * menuPtr, TkMenuEntry *mePtr, Drawable d, + GC gc, Tk_Font tkfont, + CONST Tk_FontMetrics *fmPtr, int x, int y, + int width, int height)); +static void DrawMenuSeparator _ANSI_ARGS_((TkMenu *menuPtr, + TkMenuEntry *mePtr, Drawable d, GC gc, + Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr, + int x, int y, int width, int height)); +static void DrawTearoffEntry _ANSI_ARGS_((TkMenu *menuPtr, + TkMenuEntry *mePtr, Drawable d, GC gc, + Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr, + int x, int y, int width, int height)); +static void GetEntryText _ANSI_ARGS_((TkMenuEntry *mePtr, + Tcl_DString *dStringPtr)); +static void GetMenuAccelGeometry _ANSI_ARGS_((TkMenu *menuPtr, + TkMenuEntry *mePtr, Tk_Font tkfont, + CONST Tk_FontMetrics *fmPtr, int *modWidthPtr, + int *textWidthPtr, int *heightPtr)); +static void GetMenuLabelGeometry _ANSI_ARGS_((TkMenuEntry *mePtr, + Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr, + int *widthPtr, int *heightPtr)); +static void GetMenuIndicatorGeometry _ANSI_ARGS_(( + TkMenu *menuPtr, TkMenuEntry *mePtr, + Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr, + int *widthPtr, int *heightPtr)); +static void GetMenuSeparatorGeometry _ANSI_ARGS_(( + TkMenu *menuPtr, TkMenuEntry *mePtr, + Tk_Font tkfont, CONST Tk_FontMetrics *fmPtr, + int *widthPtr, int *heightPtr)); +static void GetTearoffEntryGeometry _ANSI_ARGS_((TkMenu *menuPtr, + TkMenuEntry *mePtr, Tk_Font tkfont, + CONST Tk_FontMetrics *fmPtr, int *widthPtr, + int *heightPtr)); +static char FindMarkCharacter _ANSI_ARGS_((TkMenuEntry *mePtr)); +static void InvalidateMDEFRgns _ANSI_ARGS_((void)); + +static void MenuDefProc _ANSI_ARGS_((short message, + MenuHandle menu, Rect *menuRectPtr, + Point hitPt, short *whichItem )); +static void HandleMenuHiliteMsg (MenuRef menu, + Rect *menuRectPtr, + Point hitPt, + SInt16 *whichItem, + TkMenu *menuPtr); +static void HandleMenuDrawMsg (MenuRef menu, + Rect *menuRectPtr, + Point hitPt, + SInt16 *whichItem, + TkMenu *menuPtr); +static void HandleMenuFindItemsMsg (MenuRef menu, + Rect *menuRectPtr, + Point hitPt, + SInt16 *whichItem, + TkMenu *menuPtr); +static void HandleMenuPopUpMsg (MenuRef menu, + Rect *menuRectPtr, + Point hitPt, + SInt16 *whichItem, + TkMenu *menuPtr); +static void HandleMenuCalcItemMsg (MenuRef menu, + Rect *menuRectPtr, + Point hitPt, + SInt16 *whichItem, + TkMenu *menuPtr); + +static void MenuSelectEvent _ANSI_ARGS_((TkMenu *menuPtr)); +static void ReconfigureIndividualMenu _ANSI_ARGS_(( + TkMenu *menuPtr, MenuHandle macMenuHdl, + int base)); +static void ReconfigureMacintoshMenu _ANSI_ARGS_ (( + ClientData clientData)); +static void RecursivelyClearActiveMenu _ANSI_ARGS_(( + TkMenu *menuPtr)); +static void RecursivelyDeleteMenu _ANSI_ARGS_(( + TkMenu *menuPtr)); +static void RecursivelyInsertMenu _ANSI_ARGS_(( + TkMenu *menuPtr)); +static void SetDefaultMenubar _ANSI_ARGS_((void)); +static int SetMenuCascade _ANSI_ARGS_((TkMenu *menuPtr)); +static void mySetMenuTitle _ANSI_ARGS_((MenuHandle menuHdl, + Tcl_Obj *titlePtr)); +static void AppearanceEntryDrawWrapper _ANSI_ARGS_((TkMenuEntry *mePtr, + Rect * menuRectPtr, MenuTrackingData *mtdPtr, + Drawable d, Tk_FontMetrics *fmPtr, Tk_Font tkfont, + int x, int y, int width, int height)); +pascal void tkThemeMenuItemDrawingProc _ANSI_ARGS_ ((const Rect *inBounds, + SInt16 inDepth, Boolean inIsColorDevice, + SInt32 inUserData)); + + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXUseID -- + * + * Take the ID out of the available list for new menus. Used by the + * default menu bar's menus so that they do not get created at the tk + * level. See TkMacOSXGetNewMenuID for more information. + * + * Results: + * Returns TCL_OK if the id was not in use. Returns TCL_ERROR if the + * id was in use. + * + * Side effects: + * A hash table entry in the command table is created with a NULL + * value. + * + *---------------------------------------------------------------------- + */ + +int +TkMacOSXUseMenuID( + short macID) /* The id to take out of the table */ +{ + Tcl_HashEntry *commandEntryPtr; + int newEntry; + int iMacID = macID; /* Do this to remove compiler warning */ + + TkMenuInit(); + commandEntryPtr = Tcl_CreateHashEntry(&commandTable, (char *) iMacID, + &newEntry); + if (newEntry == 1) { + Tcl_SetHashValue(commandEntryPtr, NULL); + return TCL_OK; + } else { + return TCL_ERROR; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXGetNewMenuID -- + * + * Allocates a new menu id and marks it in use. Each menu on the + * mac must be designated by a unique id, which is a short. In + * addition, some ids are reserved by the system. Since Tk uses + * mostly dynamic menus, we must allocate and free these ids on + * the fly. We use the id as a key into a hash table; if there + * is no hash entry, we know that we can use the id. + * + * Results: + * Returns TCL_OK if succesful; TCL_ERROR if there are no more + * ids of the appropriate type to allocate. menuIDPtr contains + * the new id if succesful. + * + * Side effects: + * An entry is created for the menu in the command hash table, + * and the hash entry is stored in the appropriate field in the + * menu data structure. + * + *---------------------------------------------------------------------- + */ +int + TkMacOSXGetNewMenuID( + Tcl_Interp *interp, /* Used for error reporting */ + TkMenu *menuPtr, /* The menu we are working with */ + int cascade, /* 0 if we are working with a normal menu; + 1 if we are working with a cascade */ + short *menuIDPtr) /* The resulting id */ +{ + int found = 0; + int newEntry; + Tcl_HashEntry *commandEntryPtr = NULL; + short returnID = *menuIDPtr; + + /* + * The following code relies on shorts and unsigned chars wrapping + * when the highest value is incremented. Also, the values between + * 236 and 255 inclusive are reserved for DA's by the Mac OS. + */ + + if (!cascade) { + short curID = lastMenuID + 1; + if (curID == 236) { + curID = 256; + } + + while (curID != lastMenuID) { + int iCurID = curID; + commandEntryPtr = Tcl_CreateHashEntry(&commandTable, + (char *) iCurID, &newEntry); + if (newEntry == 1) { + found = 1; + lastMenuID = returnID = curID; + break; + } + curID++; + if (curID == 236) { + curID = 256; + } + } + } else { + + /* + * Cascade ids must be between 0 and 235 only, so they must be + * dealt with separately. + */ + + unsigned char curID = lastCascadeID + 1; + if (curID == 236) { + curID = 0; + } + + while (curID != lastCascadeID) { + int iCurID = curID; + commandEntryPtr = Tcl_CreateHashEntry(&commandTable, + (char *) iCurID, &newEntry); + if (newEntry == 1) { + found = 1; + lastCascadeID = returnID = curID; + break; + } + curID++; + if (curID == 236) { + curID = 0; + } + } + } + + if (found) { + Tcl_SetHashValue(commandEntryPtr, (char *) menuPtr); + *menuIDPtr = returnID; + return TCL_OK; + } else { + Tcl_ResetResult(interp); + Tcl_AppendResult(interp, "No more menus can be allocated.", + (char *) NULL); + return TCL_ERROR; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXFreeMenuID -- + * + * Marks the id as free. + * + * Results: + * None. + * + * Side effects: + * The hash table entry for the ID is cleared. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXFreeMenuID( + short menuID) /* The id to free */ +{ + Tcl_HashEntry *entryPtr = Tcl_FindHashEntry(&commandTable, + (char *) ((int)menuID)); + + if (entryPtr != NULL) { + Tcl_DeleteHashEntry(entryPtr); + } + if (menuID == currentAppleMenuID) { + currentAppleMenuID = 0; + } + if (menuID == currentHelpMenuID) { + currentHelpMenuID = 0; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpNewMenu -- + * + * Gets a new blank menu. Only the platform specific options are filled + * in. + * + * Results: + * Returns a standard TCL error. + * + * Side effects: + * Allocates a Macintosh menu handle and puts in the platformData + * field of the menuPtr. + * + *---------------------------------------------------------------------- + */ + +int +TkpNewMenu( + TkMenu *menuPtr) /* The common structure we are making the + * platform structure for. */ +{ + short menuID; + Str255 itemText; + int length; + MenuRef macMenuHdl; + MenuDefSpec menuDefSpec; + Tcl_Obj *useMDEFObjPtr; + int useMDEF; + int error = TCL_OK; + int err; + + + error = TkMacOSXGetNewMenuID(menuPtr->interp, menuPtr, 0, &menuID); + if (error != TCL_OK) { + return error; + } + length = strlen(Tk_PathName(menuPtr->tkwin)); + memmove(&itemText[1], Tk_PathName(menuPtr->tkwin), + (length > 230) ? 230 : length); + itemText[0] = (length > 230) ? 230 : length; + macMenuHdl = NewMenu(menuID, itemText); + + /* + * Check whether we want to use the custom mdef or not. For now + * the default is to use it unless the variable is explicitly + * set to no. + */ + + useMDEFObjPtr = Tcl_ObjGetVar2(menuPtr->interp, useMDEFVar, NULL, TCL_GLOBAL_ONLY); + if (useMDEFObjPtr == NULL + || Tcl_GetBooleanFromObj(NULL, useMDEFObjPtr, &useMDEF) == TCL_ERROR + || useMDEF) { + menuDefSpec.defType = kMenuDefProcPtr; + menuDefSpec.u.defProc = MenuDefProc; + if ((err = SetMenuDefinition(macMenuHdl, &menuDefSpec)) != noErr) { + fprintf(stderr, "SetMenuDefinition failed %d\n", err ); + } + } + menuPtr->platformData = (TkMenuPlatformData) ckalloc(sizeof(MacMenu)); + ((MacMenu *) menuPtr->platformData)->menuHdl = macMenuHdl; + SetRect(&((MacMenu *) menuPtr->platformData)->menuRect, 0, 0, 0, 0); + + if ((currentMenuBarInterp == menuPtr->interp) + && (currentMenuBarName != NULL)) { + Tk_Window parentWin = Tk_Parent(menuPtr->tkwin); + + if (strcmp(currentMenuBarName, Tk_PathName(parentWin)) == 0) { + if ((strcmp(Tk_PathName(menuPtr->tkwin) + + strlen(Tk_PathName(parentWin)), ".apple") == 0) + || (strcmp(Tk_PathName(menuPtr->tkwin) + + strlen(Tk_PathName(parentWin)), ".help") == 0)) { + if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) { + Tcl_DoWhenIdle(DrawMenuBarWhenIdle, (ClientData *) NULL); + menuBarFlags |= MENUBAR_REDRAW_PENDING; + } + } + } + } + + menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING; + Tcl_DoWhenIdle(ReconfigureMacintoshMenu, (ClientData) menuPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * TkpDestroyMenu -- + * + * Destroys platform-specific menu structures. + * + * Results: + * None. + * + * Side effects: + * All platform-specific allocations are freed up. + * + *---------------------------------------------------------------------- + */ + +void +TkpDestroyMenu( + TkMenu *menuPtr) /* The common menu structure */ +{ + MenuRef macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl; + + if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) { + Tcl_CancelIdleCall(ReconfigureMacintoshMenu, (ClientData) menuPtr); + menuPtr->menuFlags &= ~MENU_RECONFIGURE_PENDING; + } + if (GetMenuID(macMenuHdl) == currentHelpMenuID) { + MenuRef helpMenuHdl; + MenuItemIndex helpIndex; + + if ((HMGetHelpMenu(&helpMenuHdl,&helpIndex) == noErr) + && (helpMenuHdl != NULL)) { + int i, count = CountMenuItems(helpMenuHdl); + + for (i = helpItemCount; i <= count; i++) { + DeleteMenuItem(helpMenuHdl, helpItemCount); + } + } + currentHelpMenuID = 0; + } + if (menuPtr->platformData != NULL) { + MenuID menuID; + menuID = GetMenuID(macMenuHdl); + DeleteMenu(menuID); + TkMacOSXFreeMenuID(menuID); + DisposeMenu(macMenuHdl); + ckfree((char *) menuPtr->platformData); + menuPtr->platformData = NULL; + } +} + + +/* + *---------------------------------------------------------------------- + * + * SetMenuCascade -- + * + * Does any cleanup to change a menu from a normal to a cascade. + * + * Results: + * Standard Tcl error. + * + * Side effects: + * The mac menu id is reset. + * + *---------------------------------------------------------------------- + */ + +static int +SetMenuCascade( + TkMenu* menuPtr) /* The menu we are setting up to be a + * cascade. */ +{ + MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl; + MenuID newMenuID, menuID = GetMenuID(macMenuHdl); + int error = TCL_OK; + if (menuID >= 256) { + error = TkMacOSXGetNewMenuID(menuPtr->interp, menuPtr, 1, &newMenuID); + if (error == TCL_OK) { + TkMacOSXFreeMenuID(menuID); + SetMenuID (macMenuHdl,newMenuID); + } + } + return error; +} + +/* + *---------------------------------------------------------------------- + * + * TkpDestroyMenuEntry -- + * + * Cleans up platform-specific menu entry items. + * + * Results: + * None + * + * Side effects: + * All platform-specific allocations are freed up. + * + *---------------------------------------------------------------------- + */ + +void +TkpDestroyMenuEntry( + TkMenuEntry *mePtr) /* The common structure for the menu + * entry. */ +{ + TkMenu *menuPtr = mePtr->menuPtr; + + ckfree((char *) mePtr->platformEntryData); + if ((menuPtr->platformData != NULL) + && !(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) { + menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING; + Tcl_DoWhenIdle(ReconfigureMacintoshMenu, (ClientData) menuPtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * GetEntryText -- + * + * Given a menu entry, gives back the text that should go in it. + * Separators should be done by the caller, as they have to be + * handled specially. This is primarily used to do a substitution + * between "..." and the ellipsis character which looks nicer. + * + * Results: + * itemText points to the new text for the item. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +GetEntryText( + TkMenuEntry *mePtr, /* A pointer to the menu entry. */ + Tcl_DString *dStringPtr) /* The DString to put the text into. This + * will be initialized by this routine. */ +{ + Tcl_DStringInit(dStringPtr); + if (mePtr->type == TEAROFF_ENTRY) { + Tcl_DStringAppend(dStringPtr, "(Tear-off)", -1); + } else if (mePtr->imagePtr != NULL) { + Tcl_DStringAppend(dStringPtr, "(Image)", -1); + } else if (mePtr->bitmapPtr != NULL) { + Tcl_DStringAppend(dStringPtr, "(Pixmap)", -1); + } else if (mePtr->labelPtr == NULL || mePtr->labelLength == 0) { + /* + * The Mac menu manager does not like null strings. + */ + + Tcl_DStringAppend(dStringPtr, " ", -1); + } else { + int length; + char *text = Tcl_GetStringFromObj(mePtr->labelPtr, &length); + char *dStringText; + int i; + + for (i = 0; *text; text++, i++) { + if ((*text == '.') + && (*(text + 1) != '\0') && (*(text + 1) == '.') + && (*(text + 2) != '\0') && (*(text + 2) == '.')) { + Tcl_DStringAppend(dStringPtr, elipsisString, -1); + i += strlen(elipsisString) - 1; + text += 2; + } else { + Tcl_DStringSetLength(dStringPtr, + Tcl_DStringLength(dStringPtr) + 1); + dStringText = Tcl_DStringValue(dStringPtr); + dStringText[i] = *text; + } + } + } +} + +/* + *---------------------------------------------------------------------- + * + * FindMarkCharacter -- + * + * Finds the Macintosh mark character based on the font of the + * item. We calculate a good mark character based on the font + * that this item is rendered in. + * + * We try the following special mac characters. If none of them + * are present, just use the check mark. + * '' - Check mark character (\022) + * 'Â¥' - Mac Bullet character (\245) + * '' - Filled diamond (\023) + * '—' - Hollow diamond (\327) + * '‘' = Mac Long dash ("em dash") (\321) + * '-' = short dash (minus, "en dash"); + * + * Results: + * None. + * + * Side effects: + * New item is added to platform menu + * + *---------------------------------------------------------------------- + */ + +static char +FindMarkCharacter( + TkMenuEntry *mePtr) /* The entry we are finding the character + * for. */ +{ + char markChar; + Tk_Font tkfont; + + tkfont = Tk_GetFontFromObj(mePtr->menuPtr->tkwin, + (mePtr->fontPtr == NULL) ? mePtr->menuPtr->fontPtr + : mePtr->fontPtr); + + if (!TkMacOSXIsCharacterMissing(tkfont, '\022')) { + markChar = '\022'; /* Check mark */ + } else if (!TkMacOSXIsCharacterMissing(tkfont, '\245')) { + markChar = '\245'; /* Bullet */ + } else if (!TkMacOSXIsCharacterMissing(tkfont, '\023')) { + markChar = '\023'; /* Filled Diamond */ + } else if (!TkMacOSXIsCharacterMissing(tkfont, '\327')) { + markChar = '\327'; /* Hollow Diamond */ + } else if (!TkMacOSXIsCharacterMissing(tkfont, '\321')) { + markChar = '\321'; /* Long Dash */ + } else if (!TkMacOSXIsCharacterMissing(tkfont, '-')) { + markChar = '-'; /* Short Dash */ + } else { + markChar = '\022'; /* Check mark */ + } + return markChar; +} + +/* + *---------------------------------------------------------------------- + * + * SetMenuTitle -- + * + * Sets title of menu so that the text displays correctly in menubar. + * This code directly manipulates menu handle data. This code + * was originally part of an ancient Apple Developer Response mail. + * + * Results: + * None. + * + * Side effects: + * The menu handle will change size depending on the length of the + * title + * + *---------------------------------------------------------------------- + */ + +static void +mySetMenuTitle( + MenuRef menuHdl, /* The menu we are setting the title of. */ + Tcl_Obj *titlePtr) /* The C string to set the title to. */ +{ + char *title = (titlePtr == NULL) ? "" + : Tcl_GetStringFromObj(titlePtr, NULL); + Str255 menuTitle; + menuTitle [ 0 ] = strlen ( title ) + 1; + strcpy ( menuTitle + 1, title ); + SetMenuTitle ( menuHdl, menuTitle ); +} +static int ParseAccelerators(char **accelStringPtr) { + char *accelString = *accelStringPtr; + int flags = 0; + while (1) { + if ((0 == strncasecmp("Control", accelString, 6)) + && (('-' == accelString[6]) || ('+' == accelString[6]))) { + flags |= ENTRY_CONTROL_ACCEL; + accelString += 7; + } else if ((0 == strncasecmp("Ctrl", accelString, 4)) + && (('-' == accelString[4]) || ('+' == accelString[4]))) { + flags |= ENTRY_CONTROL_ACCEL; + accelString += 5; + } else if ((0 == strncasecmp("Shift", accelString, 5)) + && (('-' == accelString[5]) || ('+' == accelString[5]))) { + flags |= ENTRY_SHIFT_ACCEL; + accelString += 6; + } else if ((0 == strncasecmp("Option", accelString, 6)) + && (('-' == accelString[6]) || ('+' == accelString[6]))) { + flags |= ENTRY_OPTION_ACCEL; + accelString += 7; + } else if ((0 == strncasecmp("Opt", accelString, 3)) + && (('-' == accelString[3]) || ('+' == accelString[3]))) { + flags |= ENTRY_OPTION_ACCEL; + accelString += 4; + } else if ((0 == strncasecmp("Command", accelString, 7)) + && (('-' == accelString[7]) || ('+' == accelString[7]))) { + flags |= ENTRY_COMMAND_ACCEL; + accelString += 8; + } else if ((0 == strncasecmp("Cmd", accelString, 3)) + && (('-' == accelString[3]) || ('+' == accelString[3]))) { + flags |= ENTRY_COMMAND_ACCEL; + accelString += 4; + } else if ((0 == strncasecmp("Alt", accelString, 3)) + && (('-' == accelString[3]) || ('+' == accelString[3]))) { + flags |= ENTRY_OPTION_ACCEL; + accelString += 4; + } else if ((0 == strncasecmp("Meta", accelString, 4)) + && (('-' == accelString[4]) || ('+' == accelString[4]))) { + flags |= ENTRY_COMMAND_ACCEL; + accelString += 5; + } else { + break; + } + } + *accelStringPtr = accelString; + return flags; +} + +/* + *---------------------------------------------------------------------- + * + * TkpConfigureMenuEntry -- + * + * Processes configurations for menu entries. + * + * Results: + * Returns standard TCL result. If TCL_ERROR is returned, then + * the interp's result contains an error message. + * + * Side effects: + * Configuration information get set for mePtr; old resources + * get freed, if any need it. + * + *---------------------------------------------------------------------- + */ + +int +TkpConfigureMenuEntry( + TkMenuEntry *mePtr) /* Information about menu entry; may + * or may not already have values for + * some fields. */ +{ + TkMenu *menuPtr = mePtr->menuPtr; + int index = mePtr->index; + MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl; + MenuHandle helpMenuHdl = NULL; + + /* + * Cascade menus have to have menu IDs of less than 256. So + * we need to change the child menu if this has been configured + * for a cascade item. + */ + + if (mePtr->type == CASCADE_ENTRY) { + if ((mePtr->childMenuRefPtr != NULL) + && (mePtr->childMenuRefPtr->menuPtr != NULL)) { + MenuHandle childMenuHdl = ((MacMenu *) mePtr + ->childMenuRefPtr->menuPtr->platformData)->menuHdl; + + if (childMenuHdl != NULL) { + int error = SetMenuCascade(mePtr->childMenuRefPtr->menuPtr); + + if (error != TCL_OK) { + return error; + } + + if (menuPtr->menuType == MENUBAR) { + mySetMenuTitle(childMenuHdl, mePtr->labelPtr); + } + } + } + } + + /* + * We need to parse the accelerator string. If it has the strings + * for Command, Control, Shift or Option, we need to flag it + * so we can draw the symbols for it. We also need to precalcuate + * the position of the first real character we are drawing. + */ + + if (0 == mePtr->accelLength) { + ((EntryGeometry *)mePtr->platformEntryData)->accelTextStart = -1; + } else { + char *accelString = (mePtr->accelPtr == NULL) ? "" + : Tcl_GetStringFromObj(mePtr->accelPtr, NULL); + char *accel = accelString; + mePtr->entryFlags |= ~ENTRY_ACCEL_MASK; + + mePtr->entryFlags |= ParseAccelerators(&accelString); + + ((EntryGeometry *)mePtr->platformEntryData)->accelTextStart + = ((long) accelString - (long) accel); + } + + if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) { + menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING; + Tcl_DoWhenIdle(ReconfigureMacintoshMenu, (ClientData) menuPtr); + } + + return TCL_OK; +} + + +/* + *---------------------------------------------------------------------- + * + * ReconfigureIndividualMenu -- + * + * This routine redoes the guts of the menu. It works from + * a base item and offset, so that a regular menu will + * just have all of its items added, but the help menu will + * have all of its items appended after the apple-defined + * items. + * + * Results: + * None. + * + * Side effects: + * The Macintosh menu handle is updated + * + *---------------------------------------------------------------------- + */ + +static void +ReconfigureIndividualMenu( + TkMenu *menuPtr, /* The menu we are affecting. */ + MenuHandle macMenuHdl, /* The macintosh menu we are affecting. + * Will not necessarily be + * menuPtr->platformData because this could + * be the help menu. */ + int base) /* The last index that we do not want + * touched. 0 for normal menus; + * helpMenuItemCount for help menus. */ +{ + int count; + int index; + TkMenuEntry *mePtr; + Str255 itemText; + int parentDisabled = 0; + + for (mePtr = menuPtr->menuRefPtr->parentEntryPtr; mePtr != NULL; + mePtr = mePtr->nextCascadePtr) { + char *name = (mePtr->namePtr == NULL) ? "" + : Tcl_GetStringFromObj(mePtr->namePtr, NULL); + + if (strcmp(Tk_PathName(menuPtr->tkwin), name) == 0) { + if (mePtr->state == ENTRY_DISABLED) { + parentDisabled = 1; + } + break; + } + } + + /* + * First, we get rid of all of the old items. + */ + + count = CountMenuItems(macMenuHdl); + for (index = base; index < count; index++) { + DeleteMenuItem(macMenuHdl, base + 1); + } + + count = menuPtr->numEntries; + + for (index = 1; index <= count; index++) { + mePtr = menuPtr->entries[index - 1]; + + /* + * We have to do separators separately because SetMenuItemText + * does not parse meta-characters. + */ + + if (mePtr->type == SEPARATOR_ENTRY) { + AppendMenu(macMenuHdl, SEPARATOR_TEXT); + } else { + Tcl_DString itemTextDString; + int destWrote; + CFStringRef cf; + GetEntryText(mePtr, &itemTextDString); + cf = CFStringCreateWithCString(NULL, + Tcl_DStringValue(&itemTextDString), kCFStringEncodingUTF8); + AppendMenu(macMenuHdl, "\px"); + if (cf != NULL) { + SetMenuItemTextWithCFString(macMenuHdl, base + index, cf); + CFRelease(cf); + } else { + cf = CFSTR ("<Error>"); + SetMenuItemTextWithCFString(macMenuHdl, base + index, cf); + } + Tcl_DStringFree(&itemTextDString); + + /* + * Set enabling and disabling correctly. + */ + + if (parentDisabled || (mePtr->state == ENTRY_DISABLED)) { + DisableMenuItem(macMenuHdl, base + index); + } else { + EnableMenuItem(macMenuHdl, base + index); + } + + /* + * Set the check mark for check entries and radio entries. + */ + + SetItemMark(macMenuHdl, base + index, 0); + if ((mePtr->type == CHECK_BUTTON_ENTRY) + || (mePtr->type == RADIO_BUTTON_ENTRY)) { + CheckMenuItem(macMenuHdl, base + index, (mePtr->entryFlags + & ENTRY_SELECTED) && mePtr->indicatorOn); + if (mePtr->indicatorOn + && (mePtr->entryFlags & ENTRY_SELECTED)) { + SetItemMark(macMenuHdl, base + index, + FindMarkCharacter(mePtr)); + } + } + + if (mePtr->type == CASCADE_ENTRY) { + if ((mePtr->childMenuRefPtr != NULL) + && (mePtr->childMenuRefPtr->menuPtr != NULL)) { + MenuHandle childMenuHdl = + ((MacMenu *) mePtr->childMenuRefPtr + ->menuPtr->platformData)->menuHdl; + + if (childMenuHdl == NULL) { + childMenuHdl = ((MacMenu *) mePtr->childMenuRefPtr + ->menuPtr->platformData)->menuHdl; + } + if (childMenuHdl != NULL) { + { + SetMenuItemHierarchicalID(macMenuHdl, base + index, + GetMenuID(childMenuHdl)); + } + } + /* + * If we changed the highligthing of this menu, its + * children all have to be reconfigured so that + * their state will be reflected in the menubar. + */ + + if (!(mePtr->childMenuRefPtr->menuPtr->menuFlags + & MENU_RECONFIGURE_PENDING)) { + mePtr->childMenuRefPtr->menuPtr->menuFlags + |= MENU_RECONFIGURE_PENDING; + Tcl_DoWhenIdle(ReconfigureMacintoshMenu, + (ClientData) mePtr->childMenuRefPtr->menuPtr); + } + } + } + + if ((mePtr->type != CASCADE_ENTRY) && (mePtr->accelPtr != NULL)) { + int accelLen; + int modifiers = 0; + int hasCmd = 0; + int offset = ((EntryGeometry *)mePtr->platformEntryData)->accelTextStart; + char *accel = Tcl_GetStringFromObj(mePtr->accelPtr, &accelLen); + accelLen -= offset; + accel+= offset; + + if (mePtr->entryFlags & ENTRY_OPTION_ACCEL) { + modifiers |= kMenuOptionModifier; + } + if (mePtr->entryFlags & ENTRY_SHIFT_ACCEL) { + modifiers |= kMenuShiftModifier; + } + if (mePtr->entryFlags & ENTRY_CONTROL_ACCEL) { + modifiers |= kMenuControlModifier; + } + if (mePtr->entryFlags & ENTRY_COMMAND_ACCEL) { + hasCmd = 1; + } + if (accelLen == 1) { + if (hasCmd || (modifiers != 0 && modifiers != kMenuShiftModifier)) { + SetItemCmd(macMenuHdl, base + index, accel[0]); + if (!hasCmd) { + modifiers |= kMenuNoCommandModifier; + } + } + } else { + /* + * Now we need to convert from various textual names + * to Carbon codes + */ + char glyph = 0x0; + char first = UCHAR(accel[0]); + if (first == 'F' && (accel[1] > '0' && accel[1] <= '9')) { + int fkey = accel[1] - '0'; + if (accel[2] > '0' && accel[2] <= '9') { + fkey = 10*fkey + (accel[2] - '0'); + } + if (fkey > 0 && fkey < 16) { + glyph = kMenuF1Glyph + fkey - 1; + } + } else if (first == 'P' && 0 ==strcasecmp(accel,"pageup")) { + glyph = kMenuPageUpGlyph; + } else if (first == 'P' && 0 ==strcasecmp(accel,"pagedown")) { + glyph = kMenuPageDownGlyph; + } else if (first == 'L' && 0 ==strcasecmp(accel,"left")) { + glyph = kMenuLeftArrowGlyph; + } else if (first == 'R' && 0 ==strcasecmp(accel,"right")) { + glyph = kMenuRightArrowGlyph; + } else if (first == 'U' && 0 ==strcasecmp(accel,"up")) { + glyph = kMenuUpArrowGlyph; + } else if (first == 'D' && 0 ==strcasecmp(accel,"down")) { + glyph = kMenuDownArrowGlyph; + } else if (first == 'E' && 0 ==strcasecmp(accel,"escape")) { + glyph = kMenuEscapeGlyph; + } else if (first == 'C' && 0 ==strcasecmp(accel,"clear")) { + glyph = kMenuClearGlyph; + } else if (first == 'E' && 0 ==strcasecmp(accel,"enter")) { + glyph = kMenuEnterGlyph; + } else if (first == 'D' && 0 ==strcasecmp(accel,"backspace")) { + glyph = kMenuDeleteLeftGlyph; + } else if (first == 'S' && 0 ==strcasecmp(accel,"space")) { + glyph = kMenuSpaceGlyph; + } else if (first == 'T' && 0 ==strcasecmp(accel,"tab")) { + glyph = kMenuTabRightGlyph; + } else if (first == 'F' && 0 ==strcasecmp(accel,"delete")) { + glyph = kMenuDeleteRightGlyph; + } else if (first == 'H' && 0 ==strcasecmp(accel,"home")) { + glyph = kMenuNorthwestArrowGlyph; + } else if (first == 'R' && 0 ==strcasecmp(accel,"return")) { + glyph = kMenuReturnGlyph; + } else if (first == 'H' && 0 ==strcasecmp(accel,"help")) { + glyph = kMenuHelpGlyph; + } else if (first == 'P' && 0 ==strcasecmp(accel,"power")) { + glyph = kMenuPowerGlyph; + } + if (glyph != 0x0) { + SetMenuItemKeyGlyph(macMenuHdl, base + index, glyph); + if (modifiers == 0) { + if (!hasCmd) { + modifiers |= kMenuNoCommandModifier; + } + } + } + } + + SetMenuItemModifiers(macMenuHdl, base + index, modifiers); + } + } + } +} + +/* + *---------------------------------------------------------------------- + * + * ReconfigureMacintoshMenu -- + * + * Rebuilds the Macintosh MenuHandle items from the menu. Called + * usually as an idle handler, but can be called synchronously + * if the menu is about to be posted. + * + * Results: + * None. + * + * Side effects: + * Configuration information get set for mePtr; old resources + * get freed, if any need it. + * + *---------------------------------------------------------------------- + */ + +static void +ReconfigureMacintoshMenu( + ClientData clientData) /* Information about menu entry; may + * or may not already have values for + * some fields. */ +{ + TkMenu *menuPtr = (TkMenu *) clientData; + MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl; + MenuHandle helpMenuHdl = NULL; + + menuPtr->menuFlags &= ~MENU_RECONFIGURE_PENDING; + + if (NULL == macMenuHdl) { + return; + } + + ReconfigureIndividualMenu(menuPtr, macMenuHdl, 0); + + if (menuPtr->menuFlags & MENU_APPLE_MENU) { + AppendResMenu(macMenuHdl, 'DRVR'); + } + if (GetMenuID(macMenuHdl) == currentHelpMenuID) { + MenuItemIndex helpIndex; + HMGetHelpMenu(&helpMenuHdl,&helpIndex); + if (helpMenuHdl != NULL) { + ReconfigureIndividualMenu(menuPtr, helpMenuHdl, helpItemCount); + } + } + + if (menuPtr->menuType == MENUBAR) { + if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) { + Tcl_DoWhenIdle(DrawMenuBarWhenIdle, (ClientData *) NULL); + menuBarFlags |= MENUBAR_REDRAW_PENDING; + } + } +} + +/* + *---------------------------------------------------------------------- + * + * CompleteIdlers -- + * + * Completes all idle handling so that the menus are in sync when + * the user invokes them with the mouse. + * + * Results: + * None. + * + * Side effects: + * The Macintosh menu handles are flushed out. + * + *---------------------------------------------------------------------- + */ + +static void +CompleteIdlers( + TkMenu *menuPtr) /* The menu we are completing. */ +{ + int i; + + if (menuPtr->menuFlags & MENU_RECONFIGURE_PENDING) { + Tcl_CancelIdleCall(ReconfigureMacintoshMenu, (ClientData) menuPtr); + ReconfigureMacintoshMenu((ClientData) menuPtr); + } + + for (i = 0; i < menuPtr->numEntries; i++) { + if (menuPtr->entries[i]->type == CASCADE_ENTRY) { + if ((menuPtr->entries[i]->childMenuRefPtr != NULL) + && (menuPtr->entries[i]->childMenuRefPtr->menuPtr + != NULL)) { + CompleteIdlers(menuPtr->entries[i]->childMenuRefPtr + ->menuPtr); + } + } + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpPostMenu -- + * + * Posts a menu on the screen + * + * Results: + * None. + * + * Side effects: + * The menu is posted and handled. + * + *---------------------------------------------------------------------- + */ + +int +TkpPostMenu( + Tcl_Interp *interp, /* The interpreter this menu lives in */ + TkMenu *menuPtr, /* The menu we are posting */ + int x, /* The global x-coordinate of the top, left- + * hand corner of where the menu is supposed + * to be posted. */ + int y) /* The global y-coordinate */ +{ + MenuHandle macMenuHdl = ((MacMenu *) menuPtr->platformData)->menuHdl; + long popUpResult; + int result; + int oldMode; + + if (inPostMenu) { + Tcl_AppendResult(interp, + "Cannot call post menu while already posting menu", + (char *) NULL); + result = TCL_ERROR; + } else { + Window dummyWin; + unsigned int state; + int dummy, mouseX, mouseY; + short menuID; + Window window; + int oldWidth = menuPtr->totalWidth; + Tk_Window parentWindow = Tk_Parent(menuPtr->tkwin); + + inPostMenu++; + + result = TkPreprocessMenu(menuPtr); + if (result != TCL_OK) { + inPostMenu--; + return result; + } + + /* + * The post commands could have deleted the menu, which means + * we are dead and should go away. + */ + + if (menuPtr->tkwin == NULL) { + inPostMenu--; + return TCL_OK; + } + + CompleteIdlers(menuPtr); + if (menuBarFlags & MENUBAR_REDRAW_PENDING) { + Tcl_CancelIdleCall(DrawMenuBarWhenIdle, (ClientData *) NULL); + DrawMenuBarWhenIdle((ClientData *) NULL); + } + + if (NULL == parentWindow) { + tearoffStruct.excludeRect.top = tearoffStruct.excludeRect.left + = tearoffStruct.excludeRect.bottom + = tearoffStruct.excludeRect.right = SHRT_MAX; + } else { + int left, top; + + Tk_GetRootCoords(parentWindow, &left, &top); + tearoffStruct.excludeRect.left = left; + tearoffStruct.excludeRect.top = top; + tearoffStruct.excludeRect.right = left + Tk_Width(parentWindow); + tearoffStruct.excludeRect.bottom = top + Tk_Height(parentWindow); + if (Tk_Class(parentWindow) == Tk_GetUid("Menubutton")) { + TkWindow *parentWinPtr = (TkWindow *) parentWindow; + TkMenuButton *mbPtr = + (TkMenuButton *) parentWinPtr->instanceData; + int menuButtonWidth = Tk_Width(parentWindow) + - 2 * (mbPtr->highlightWidth + mbPtr->borderWidth + 1); + menuPtr->totalWidth = menuButtonWidth > menuPtr->totalWidth + ? menuButtonWidth : menuPtr->totalWidth; + } + } + + InsertMenu(macMenuHdl, -1); + RecursivelyInsertMenu(menuPtr); + CountMenuItems(macMenuHdl); + + oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); + popUpResult = PopUpMenuSelect(macMenuHdl, y, x, menuPtr->active); + Tcl_SetServiceMode(oldMode); + + menuPtr->totalWidth = oldWidth; + RecursivelyDeleteMenu(menuPtr); + DeleteMenu(GetMenuID(macMenuHdl)); + + /* + * Simulate the mouse up. + */ + + XQueryPointer(NULL, None, &dummyWin, &dummyWin, &mouseX, + &mouseY, &dummy, &dummy, &state); + window = Tk_WindowId(menuPtr->tkwin); + TkGenerateButtonEvent(mouseX, mouseY, window, state); + + /* + * Dispatch the command. + */ + + menuID = HiWord(popUpResult); + if (menuID != 0) { + result = TkMacOSXDispatchMenuEvent(menuID, LoWord(popUpResult)); + } else { + TkMacOSXHandleTearoffMenu(); + result = TCL_OK; + } + + /* + * Be careful, here. The command executed in handling the menu event + * could destroy the window. Don't try to do anything with it then. + */ + + if (menuPtr->tkwin) { + InvalidateMDEFRgns(); + RecursivelyClearActiveMenu(menuPtr); + } + inPostMenu--; + } + return result; +} + +/* + *---------------------------------------------------------------------- + * + * TkpMenuNewEntry -- + * + * Adds a pointer to a new menu entry structure with the platform- + * specific fields filled in. The Macintosh uses the + * platformEntryData field of the TkMenuEntry record to store + * geometry information. + * + * Results: + * Standard TCL error. + * + * Side effects: + * Storage gets allocated. New menu entry data is put into the + * platformEntryData field of the mePtr. + * + *---------------------------------------------------------------------- + */ + +int +TkpMenuNewEntry( + TkMenuEntry *mePtr) /* The menu we are adding an entry to */ +{ + EntryGeometry *geometryPtr = + (EntryGeometry *) ckalloc(sizeof(EntryGeometry)); + TkMenu *menuPtr = mePtr->menuPtr; + + geometryPtr->accelTextStart = 0; + geometryPtr->accelTextWidth = 0; + geometryPtr->nonAccelMargin = 0; + geometryPtr->modifierWidth = 0; + mePtr->platformEntryData = (TkMenuPlatformEntryData) geometryPtr; + if (!(menuPtr->menuFlags & MENU_RECONFIGURE_PENDING)) { + menuPtr->menuFlags |= MENU_RECONFIGURE_PENDING; + Tcl_DoWhenIdle(ReconfigureMacintoshMenu, (ClientData) menuPtr); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * + * Tk_MacOSXTurnOffMenus -- + * + * Turns off all the menu drawing code. This is more than just disabling + * the "menu" command, this means that Tk will NEVER touch the menubar. + * It is needed in the Plugin, where Tk does not own the menubar. + * + * Results: + * None. + * + * Side effects: + * A flag is set which will disable all menu drawing. + * + *---------------------------------------------------------------------- + */ + +void +Tk_MacOSXTurnOffMenus() +{ + gNoTkMenus = 1; +} + +/* + *---------------------------------------------------------------------- + * + * + * DrawMenuBarWhenIdle -- + * + * Update the menu bar next time there is an idle event. + * + * Results: + * None. + * + * Side effects: + * Menu bar is redrawn. + * + *---------------------------------------------------------------------- + */ + +static void +DrawMenuBarWhenIdle( + ClientData clientData) /* ignored here */ +{ + TkMenuReferences *menuRefPtr; + TkMenu *appleMenuPtr, *helpMenuPtr; + MenuHandle macMenuHdl; + Tcl_HashEntry *hashEntryPtr; + + /* + * If we have been turned off, exit. + */ + + if (gNoTkMenus) { + return; + } + + /* + * We need to clear the apple and help menus of any extra items. + */ + + if (currentAppleMenuID != 0) { + hashEntryPtr = Tcl_FindHashEntry(&commandTable, + (char *) ((int)currentAppleMenuID)); + appleMenuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr); + TkpDestroyMenu(appleMenuPtr); + TkpNewMenu(appleMenuPtr); + appleMenuPtr->menuFlags &= ~MENU_APPLE_MENU; + appleMenuPtr->menuFlags |= MENU_RECONFIGURE_PENDING; + Tcl_DoWhenIdle(ReconfigureMacintoshMenu, + (ClientData) appleMenuPtr); + } + + if (currentHelpMenuID != 0) { + hashEntryPtr = Tcl_FindHashEntry(&commandTable, + (char *) ((int)currentHelpMenuID)); + helpMenuPtr = (TkMenu *) Tcl_GetHashValue(hashEntryPtr); + TkpDestroyMenu(helpMenuPtr); + TkpNewMenu(helpMenuPtr); + helpMenuPtr->menuFlags &= ~MENU_HELP_MENU; + helpMenuPtr->menuFlags |= MENU_RECONFIGURE_PENDING; + Tcl_DoWhenIdle(ReconfigureMacintoshMenu, + (ClientData) helpMenuPtr); + } + + /* + * We need to find the clone of this menu that is the menubar. + * Once we do that, for every cascade in the menu, we need to + * insert the Mac menu in the Mac menubar. Finally, we need + * to redraw the menubar. + */ + + menuRefPtr = NULL; + if (currentMenuBarName != NULL) { + menuRefPtr = TkFindMenuReferences(currentMenuBarInterp, + currentMenuBarName); + } + if (menuRefPtr != NULL) { + TkMenu *menuPtr, *menuBarPtr; + TkMenu *cascadeMenuPtr; + char *appleMenuName, *helpMenuName; + int appleIndex = -1, helpIndex = -1; + int i; + + menuPtr = menuRefPtr->menuPtr; + if (menuPtr != NULL) { + TkMenuReferences *specialMenuRefPtr; + TkMenuEntry *specialEntryPtr; + + appleMenuName = ckalloc(strlen(currentMenuBarName) + + 1 + strlen(".apple") + 1); + sprintf(appleMenuName, "%s.apple", + Tk_PathName(menuPtr->tkwin)); + specialMenuRefPtr = TkFindMenuReferences(currentMenuBarInterp, + appleMenuName); + if ((specialMenuRefPtr != NULL) + && (specialMenuRefPtr->menuPtr != NULL)) { + for (specialEntryPtr + = specialMenuRefPtr->parentEntryPtr; + specialEntryPtr != NULL; + specialEntryPtr + = specialEntryPtr->nextCascadePtr) { + if (specialEntryPtr->menuPtr == menuPtr) { + appleIndex = specialEntryPtr->index; + break; + } + } + } + ckfree(appleMenuName); + + helpMenuName = ckalloc(strlen(currentMenuBarName) + + 1 + strlen(".help") + 1); + sprintf(helpMenuName, "%s.help", + Tk_PathName(menuPtr->tkwin)); + specialMenuRefPtr = TkFindMenuReferences(currentMenuBarInterp, + helpMenuName); + if ((specialMenuRefPtr != NULL) + && (specialMenuRefPtr->menuPtr != NULL)) { + for (specialEntryPtr + = specialMenuRefPtr->parentEntryPtr; + specialEntryPtr != NULL; + specialEntryPtr + = specialEntryPtr->nextCascadePtr) { + if (specialEntryPtr->menuPtr == menuPtr) { + helpIndex = specialEntryPtr->index; + break; + } + } + } + ckfree(helpMenuName); + + } + + for (menuBarPtr = menuPtr; + (menuBarPtr != NULL) + && (menuBarPtr->menuType != MENUBAR); + menuBarPtr = menuBarPtr->nextInstancePtr) { + + /* + * Null loop body. + */ + + } + + if (menuBarPtr == NULL) { + SetDefaultMenubar(); + } else { + if (menuBarPtr->tearoff != menuPtr->tearoff) { + if (menuBarPtr->tearoff) { + appleIndex = (-1 == appleIndex) ? appleIndex + : appleIndex + 1; + helpIndex = (-1 == helpIndex) ? helpIndex + : helpIndex + 1; + } else { + appleIndex = (-1 == appleIndex) ? appleIndex + : appleIndex - 1; + helpIndex = (-1 == helpIndex) ? helpIndex + : helpIndex - 1; + } + } + ClearMenuBar(); + + if (appleIndex == -1) { + InsertMenu(tkAppleMenu, 0); + currentAppleMenuID = 0; + } else { + short appleID; + appleMenuPtr = menuBarPtr->entries[appleIndex] + ->childMenuRefPtr->menuPtr; + TkpDestroyMenu(appleMenuPtr); + TkMacOSXGetNewMenuID(appleMenuPtr->interp, appleMenuPtr, 0, + &appleID); + macMenuHdl = NewMenu(appleID, "\p\024"); + appleMenuPtr->platformData = + (TkMenuPlatformData) ckalloc(sizeof(MacMenu)); + ((MacMenu *)appleMenuPtr->platformData)->menuHdl + = macMenuHdl; + SetRect(&((MacMenu *) appleMenuPtr->platformData)->menuRect, + 0, 0, 0, 0); + appleMenuPtr->menuFlags |= MENU_APPLE_MENU; + if (!(appleMenuPtr->menuFlags + & MENU_RECONFIGURE_PENDING)) { + appleMenuPtr->menuFlags |= MENU_RECONFIGURE_PENDING; + Tcl_DoWhenIdle(ReconfigureMacintoshMenu, + (ClientData) appleMenuPtr); + } + InsertMenu(macMenuHdl, 0); + RecursivelyInsertMenu(appleMenuPtr); + currentAppleMenuID = appleID; + } + if (helpIndex == -1) { + currentHelpMenuID = 0; + } + + for (i = 0; i < menuBarPtr->numEntries; i++) { + if (i == appleIndex) { + if (menuBarPtr->entries[i]->state == ENTRY_DISABLED) { + DisableMenuItem(((MacMenu *) menuBarPtr->entries[i] + ->childMenuRefPtr->menuPtr + ->platformData)->menuHdl, + 0); + } else { + EnableMenuItem(((MacMenu *) menuBarPtr->entries[i] + ->childMenuRefPtr->menuPtr + ->platformData)->menuHdl, + 0); + } + continue; + } else if (i == helpIndex) { + TkMenu *helpMenuPtr = menuBarPtr->entries[i] + ->childMenuRefPtr->menuPtr; + MenuHandle helpMenuHdl = NULL; + + if (helpMenuPtr == NULL) { + continue; + } + helpMenuPtr->menuFlags |= MENU_HELP_MENU; + if (!(helpMenuPtr->menuFlags + & MENU_RECONFIGURE_PENDING)) { + helpMenuPtr->menuFlags + |= MENU_RECONFIGURE_PENDING; + Tcl_DoWhenIdle(ReconfigureMacintoshMenu, + (ClientData) helpMenuPtr); + } + macMenuHdl = + ((MacMenu *) helpMenuPtr->platformData)->menuHdl; + currentHelpMenuID = GetMenuID(macMenuHdl); + } else if (menuBarPtr->entries[i]->type + == CASCADE_ENTRY) { + if ((menuBarPtr->entries[i]->childMenuRefPtr != NULL) + && menuBarPtr->entries[i]->childMenuRefPtr + ->menuPtr != NULL) { + cascadeMenuPtr = menuBarPtr->entries[i] + ->childMenuRefPtr->menuPtr; + macMenuHdl = ((MacMenu *) cascadeMenuPtr + ->platformData)->menuHdl; + DeleteMenu(GetMenuID(macMenuHdl)); + InsertMenu(macMenuHdl, 0); + RecursivelyInsertMenu(cascadeMenuPtr); + if (menuBarPtr->entries[i]->state == ENTRY_DISABLED) { + DisableMenuItem(((MacMenu *) menuBarPtr->entries[i] + ->childMenuRefPtr->menuPtr + ->platformData)->menuHdl, + 0); + } else { + EnableMenuItem(((MacMenu *) menuBarPtr->entries[i] + ->childMenuRefPtr->menuPtr + ->platformData)->menuHdl, + 0); + } + } + } + } + } + } else { + SetDefaultMenubar(); + } + DrawMenuBar(); + menuBarFlags &= ~MENUBAR_REDRAW_PENDING; +} + + +/* + *---------------------------------------------------------------------- + * + * RecursivelyInsertMenu -- + * + * Puts all of the cascades of this menu in the Mac hierarchical list. + * + * + * Results: + * None. + * + * Side effects: + * The menubar is changed. + * + *---------------------------------------------------------------------- + */ + +static void +RecursivelyInsertMenu( + TkMenu *menuPtr) /* All of the cascade items in this menu + * will be inserted into the mac menubar. */ +{ + int i; + TkMenu *cascadeMenuPtr; + MenuHandle macMenuHdl; + + for (i = 0; i < menuPtr->numEntries; i++) { + if (menuPtr->entries[i]->type == CASCADE_ENTRY) { + if ((menuPtr->entries[i]->childMenuRefPtr != NULL) + && (menuPtr->entries[i]->childMenuRefPtr->menuPtr + != NULL)) { + cascadeMenuPtr = menuPtr->entries[i]->childMenuRefPtr->menuPtr; + macMenuHdl = + ((MacMenu *) cascadeMenuPtr->platformData)->menuHdl; + InsertMenu(macMenuHdl, -1); + RecursivelyInsertMenu(cascadeMenuPtr); + } + } + } +} + +/* + *---------------------------------------------------------------------- + * + * RecursivelyDeleteMenu -- + * + * Takes all of the cascades of this menu out of the Mac hierarchical + * list. + * + * + * Results: + * None. + * + * Side effects: + * The menubar is changed. + * + *---------------------------------------------------------------------- + */ + +static void +RecursivelyDeleteMenu( + TkMenu *menuPtr) /* All of the cascade items in this menu + * will be inserted into the mac menubar. */ +{ + int i; + TkMenu *cascadeMenuPtr; + MenuHandle macMenuHdl; + + for (i = 0; i < menuPtr->numEntries; i++) { + if (menuPtr->entries[i]->type == CASCADE_ENTRY) { + if ((menuPtr->entries[i]->childMenuRefPtr != NULL) + && (menuPtr->entries[i]->childMenuRefPtr->menuPtr + != NULL)) { + cascadeMenuPtr = menuPtr->entries[i]->childMenuRefPtr->menuPtr; + macMenuHdl = + ((MacMenu *) cascadeMenuPtr->platformData)->menuHdl; + DeleteMenu(GetMenuID(macMenuHdl)); + RecursivelyInsertMenu(cascadeMenuPtr); + } + } + } +} + +/* + *---------------------------------------------------------------------- + * + * SetDefaultMenubar -- + * + * Puts the Apple, File and Edit menus into the Macintosh menubar. + * + * Results: + * None. + * + * Side effects: + * The menubar is changed. + * + *---------------------------------------------------------------------- + */ + +static void +SetDefaultMenubar() +{ + if (currentMenuBarName != NULL) { + ckfree(currentMenuBarName); + currentMenuBarName = NULL; + } + currentMenuBarOwner = NULL; + ClearMenuBar(); + InsertMenu(tkAppleMenu, 0); + InsertMenu(tkFileMenu, 0); + InsertMenu(tkEditMenu, 0); + if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) { + Tcl_DoWhenIdle(DrawMenuBarWhenIdle, (ClientData *) NULL); + menuBarFlags |= MENUBAR_REDRAW_PENDING; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpSetMainMenubar -- + * + * Puts the menu associated with a window into the menubar. Should + * only be called when the window is in front. + * + * Results: + * None. + * + * Side effects: + * The menubar is changed. + * + *---------------------------------------------------------------------- + */ + +void +TkpSetMainMenubar( + Tcl_Interp *interp, /* The interpreter of the application */ + Tk_Window tkwin, /* The frame we are setting up */ + char *menuName) /* The name of the menu to put in front. + * If NULL, use the default menu bar. + */ +{ + TkWindow *winPtr = (TkWindow *) tkwin; + CGrafPtr winPort; + WindowRef macWindowPtr; + WindowRef frontNonFloating; + + winPort=TkMacOSXGetDrawablePort(winPtr->window); + if (!winPort) { + return; + } + macWindowPtr = GetWindowFromPort(winPort); + + frontNonFloating = FrontNonFloatingWindow(); + if ((macWindowPtr == NULL) || (macWindowPtr != frontNonFloating)) { + return; + } + + if ((currentMenuBarInterp != interp) + || (currentMenuBarOwner != tkwin) + || (currentMenuBarName == NULL) + || (menuName == NULL) + || (strcmp(menuName, currentMenuBarName) != 0)) { + Tk_Window searchWindow; + TopLevelMenubarList *listPtr; + + if (currentMenuBarName != NULL) { + ckfree(currentMenuBarName); + } + + if (menuName == NULL) { + searchWindow = tkwin; + if (strcmp(Tk_Class(searchWindow), "Menu") == 0) { + TkMenuReferences *menuRefPtr; + + menuRefPtr = TkFindMenuReferences(interp, Tk_PathName(tkwin)); + if (menuRefPtr != NULL) { + TkMenu *menuPtr = menuRefPtr->menuPtr; + if (menuPtr != NULL) { + menuPtr = menuPtr->masterMenuPtr; + searchWindow = menuPtr->tkwin; + } + } + } + for (; searchWindow != NULL; + searchWindow = Tk_Parent(searchWindow)) { + + for (listPtr = windowListPtr; listPtr != NULL; + listPtr = listPtr->nextPtr) { + if (listPtr->tkwin == searchWindow) { + break; + } + } + if (listPtr != NULL) { + menuName = Tk_PathName(listPtr->menuPtr->masterMenuPtr + ->tkwin); + break; + } + } + } + + if (menuName == NULL) { + currentMenuBarName = NULL; + } else { + currentMenuBarName = ckalloc(strlen(menuName) + 1); + strcpy(currentMenuBarName, menuName); + } + currentMenuBarOwner = tkwin; + currentMenuBarInterp = interp; + } + if (!(menuBarFlags & MENUBAR_REDRAW_PENDING)) { + Tcl_DoWhenIdle(DrawMenuBarWhenIdle, (ClientData *) NULL); + menuBarFlags |= MENUBAR_REDRAW_PENDING; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpSetWindowMenuBar -- + * + * Associates a given menu with a window. + * + * Results: + * None. + * + * Side effects: + * On Windows and UNIX, associates the platform menu with the + * platform window. + * + *---------------------------------------------------------------------- + */ + +void +TkpSetWindowMenuBar( + Tk_Window tkwin, /* The window we are setting the menu in */ + TkMenu *menuPtr) /* The menu we are setting */ +{ + TopLevelMenubarList *listPtr, *prevPtr; + + /* + * Remove any existing reference to this window. + */ + + for (prevPtr = NULL, listPtr = windowListPtr; + listPtr != NULL; + prevPtr = listPtr, listPtr = listPtr->nextPtr) { + if (listPtr->tkwin == tkwin) { + break; + } + } + + if (listPtr != NULL) { + if (prevPtr != NULL) { + prevPtr->nextPtr = listPtr->nextPtr; + } else { + windowListPtr = listPtr->nextPtr; + } + ckfree((char *) listPtr); + } + + if (menuPtr != NULL) { + listPtr = (TopLevelMenubarList *) ckalloc(sizeof(TopLevelMenubarList)); + listPtr->nextPtr = windowListPtr; + windowListPtr = listPtr; + listPtr->tkwin = tkwin; + listPtr->menuPtr = menuPtr; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXDispatchMenuEvent -- + * + * Given a menu id and an item, dispatches the command associated + * with it. + * + * Results: + * None. + * + * Side effects: + * Commands get executed. + * + *---------------------------------------------------------------------- + */ + +int +TkMacOSXDispatchMenuEvent( + int menuID, /* The menu id of the menu we are invoking */ + int index) /* The one-based index of the item that was + * selected. */ +{ + int result = TCL_OK; + if (menuID != 0) { + if (menuID == kHMHelpMenuID) { + if (currentMenuBarOwner != NULL) { + TkMenuReferences *helpMenuRef; + char *helpMenuName = ckalloc(strlen(currentMenuBarName) + + strlen(".help") + 1); + sprintf(helpMenuName, "%s.help", currentMenuBarName); + helpMenuRef = TkFindMenuReferences(currentMenuBarInterp, + helpMenuName); + ckfree(helpMenuName); + if ((helpMenuRef != NULL) && (helpMenuRef->menuPtr != NULL)) { + int newIndex = index - helpItemCount - 1; + result = TkInvokeMenu(currentMenuBarInterp, + helpMenuRef->menuPtr, newIndex); + } + } + } else { + Tcl_HashEntry *commandEntryPtr = + Tcl_FindHashEntry(&commandTable, (char *) ((int)menuID)); + if (commandEntryPtr != NULL) { + TkMenu *menuPtr = (TkMenu *) Tcl_GetHashValue(commandEntryPtr); + if ((currentAppleMenuID == menuID) + && (index > menuPtr->numEntries + 1)) { + Str255 itemText; + + GetMenuItemText(GetMenuHandle(menuID), index, itemText); + result = TCL_OK; + } else { + result = TkInvokeMenu(menuPtr->interp, menuPtr, index - 1); + } + } else { + return TCL_ERROR; + } + } + } + return result; +} + +/* + *---------------------------------------------------------------------- + * + * GetMenuIndicatorGeometry -- + * + * Gets the width and height of the indicator area of a menu. + * + * Results: + * widthPtr and heightPtr are set. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +GetMenuIndicatorGeometry ( + TkMenu *menuPtr, /* The menu we are drawing */ + TkMenuEntry *mePtr, /* The entry we are measuring */ + Tk_Font tkfont, /* Precalculated font */ + CONST Tk_FontMetrics *fmPtr, /* Precalculated font metrics */ + int *widthPtr, /* The resulting width */ + int *heightPtr) /* The resulting height */ +{ + char markChar; + + *heightPtr = fmPtr->linespace; + + markChar = (char) FindMarkCharacter(mePtr); + *widthPtr = Tk_TextWidth(tkfont, &markChar, 1) + 4; +} + +/* + *---------------------------------------------------------------------- + * + * GetMenuAccelGeometry -- + * + * Gets the width and height of the accelerator area of a menu. + * + * Results: + * widthPtr and heightPtr are set. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +GetMenuAccelGeometry ( + TkMenu *menuPtr, /* The menu we are measuring */ + TkMenuEntry *mePtr, /* The entry we are measuring */ + Tk_Font tkfont, /* The precalculated font */ + CONST Tk_FontMetrics *fmPtr, /* The precalculated font metrics */ + int *modWidthPtr, /* The width of all of the key + * modifier symbols. */ + int *textWidthPtr, /* The resulting width */ + int *heightPtr) /* The resulting height */ +{ + *heightPtr = fmPtr->linespace; + *modWidthPtr = 0; + if (mePtr->type == CASCADE_ENTRY) { + *textWidthPtr = SICN_HEIGHT; + *modWidthPtr = Tk_TextWidth(tkfont, "W", 1); + } else if (0 == mePtr->accelLength) { + *textWidthPtr = 0; + } else { + char *accel = (mePtr->accelPtr == NULL) ? "" + : Tcl_GetStringFromObj(mePtr->accelPtr, NULL); + + if (NULL == GetResource('SICN', SICN_RESOURCE_NUMBER)) { + *textWidthPtr = Tk_TextWidth(tkfont, accel, mePtr->accelLength); + } else { + int emWidth = Tk_TextWidth(tkfont, "W", 1) + 1; + if ((mePtr->entryFlags & ENTRY_ACCEL_MASK) == 0) { + int width = Tk_TextWidth(tkfont, accel, mePtr->accelLength); + *textWidthPtr = emWidth; + if (width < emWidth) { + *modWidthPtr = 0; + } else { + *modWidthPtr = width - emWidth; + } + } else { + int length = ((EntryGeometry *)mePtr->platformEntryData) + ->accelTextStart; + if (mePtr->entryFlags & ENTRY_CONTROL_ACCEL) { + *modWidthPtr += CONTROL_ICON_WIDTH; + } + if (mePtr->entryFlags & ENTRY_SHIFT_ACCEL) { + *modWidthPtr += SHIFT_ICON_WIDTH; + } + if (mePtr->entryFlags & ENTRY_OPTION_ACCEL) { + *modWidthPtr += OPTION_ICON_WIDTH; + } + if (mePtr->entryFlags & ENTRY_COMMAND_ACCEL) { + *modWidthPtr += COMMAND_ICON_WIDTH; + } + if (1 == (mePtr->accelLength - length)) { + *textWidthPtr = emWidth; + } else { + *textWidthPtr += Tk_TextWidth(tkfont, accel + + length, mePtr->accelLength - length); + } + } + } + } +} + +/* + *---------------------------------------------------------------------- + * + * GetTearoffEntryGeometry -- + * + * Gets the width and height of of a tearoff entry. + * + * Results: + * widthPtr and heightPtr are set. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +GetTearoffEntryGeometry ( + TkMenu *menuPtr, /* The menu we are drawing */ + TkMenuEntry *mePtr, /* The entry we are measuring */ + Tk_Font tkfont, /* The precalculated font */ + CONST Tk_FontMetrics *fmPtr, /* The precalculated font metrics */ + int *widthPtr, /* The resulting width */ + int *heightPtr) /* The resulting height */ +{ + if ((GetResource('MDEF', 591) == NULL) && + (menuPtr->menuType == MASTER_MENU)) { + *heightPtr = fmPtr->linespace; + *widthPtr = 0; + } else { + *widthPtr = *heightPtr = 0; + } +} + +/* + *---------------------------------------------------------------------- + * + * GetMenuSeparatorGeometry -- + * + * Gets the width and height of menu separator. + * + * Results: + * widthPtr and heightPtr are set. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +GetMenuSeparatorGeometry( + TkMenu *menuPtr, /* The menu we are drawing */ + TkMenuEntry *mePtr, /* The entry we are measuring */ + Tk_Font tkfont, /* The precalculated font */ + CONST Tk_FontMetrics *fmPtr, /* The precalcualted font metrics */ + int *widthPtr, /* The resulting width */ + int *heightPtr) /* The resulting height */ +{ + SInt16 outHeight; + + GetThemeMenuSeparatorHeight(&outHeight); + *widthPtr = 0; + *heightPtr = outHeight; +} + +/* + *---------------------------------------------------------------------- + * + * DrawMenuEntryIndicator -- + * + * This procedure draws the indicator part of a menu. + * + * Results: + * None. + * + * Side effects: + * Commands are output to X to display the menu in its + * current mode. + * + *---------------------------------------------------------------------- + */ + +static void +DrawMenuEntryIndicator( + TkMenu *menuPtr, /* The menu we are drawing */ + TkMenuEntry *mePtr, /* The entry we are drawing */ + Drawable d, /* The drawable we are drawing */ + GC gc, /* The GC we are drawing with */ + GC indicatorGC, /* The GC to use for the indicator */ + Tk_Font tkfont, /* The precalculated font */ + CONST Tk_FontMetrics *fmPtr, /* The precalculated font metrics */ + int x, /* topleft hand corner of entry */ + int y, /* topleft hand corner of entry */ + int width, /* width of entry */ + int height) /* height of entry */ +{ + if ((mePtr->type == CHECK_BUTTON_ENTRY) || + (mePtr->type == RADIO_BUTTON_ENTRY)) { + if (mePtr->indicatorOn + && (mePtr->entryFlags & ENTRY_SELECTED)) { + int baseline; + short markShort; + + baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2; + GetItemMark(((MacMenu *) menuPtr->platformData)->menuHdl, + mePtr->index + 1, &markShort); + if (markShort != 0) { + char markChar; + char markCharUTF[TCL_UTF_MAX + 1]; + int dstWrote; + + markChar = (char) markShort; + /* + * Not sure if this is the correct encoding, but this function + * doesn't appear to be used at all in, since the Carbon Menus + * draw themselves + */ + Tcl_ExternalToUtf(NULL, NULL, &markChar, 1, 0, NULL, + markCharUTF, TCL_UTF_MAX + 1, NULL, &dstWrote, NULL); + Tk_DrawChars(menuPtr->display, d, gc, tkfont, markCharUTF, + dstWrote, x + 2, baseline); + } + } + } +} + +/* + *---------------------------------------------------------------------- + * + * DrawMenuBackground -- + * + * If Appearance is present, draws the Appearance background + * + * Results: + * Nothing + * + * Side effects: + * Commands are output to X to display the menu in its + * current mode. + * + *---------------------------------------------------------------------- + */ +static void +DrawMenuBackground( + Rect *menuRectPtr, /* The menu rect */ + Drawable d, /* What we are drawing into */ + ThemeMenuType type /* Type of menu */ + ) +{ + CGrafPtr saveWorld; + GDHandle saveDevice; + GWorldPtr destPort; + + destPort = TkMacOSXGetDrawablePort(d); + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + TkMacOSXSetUpClippingRgn(d); + DrawThemeMenuBackground (menuRectPtr, type); + SetGWorld(saveWorld, saveDevice); + return; +} + +/* + *---------------------------------------------------------------------- + * + * DrawSICN -- + * + * Given a resource id and an index, loads the appropriate SICN + * and draws it into a given drawable using the given gc. + * + * Results: + * Returns 1 if the SICN was found, 0 if not found. + * + * Side effects: + * Commands are output to X to display the menu in its + * current mode. + * + *---------------------------------------------------------------------- + */ +static int +DrawSICN( + int resourceID, /* The resource # of the SICN table */ + int index, /* The index into the SICN table of the + * icon we want. */ + Drawable d, /* What we are drawing into */ + GC gc, /* The GC to draw with */ + int x, /* The left hand coord of the SICN */ + int y) /* The top coord of the SICN */ +{ + Handle sicnHandle = (Handle) GetResource('SICN', SICN_RESOURCE_NUMBER); + + if (NULL == sicnHandle) { + return 0; + } else { + BitMap sicnBitmap; + Rect destRect; + CGrafPtr saveWorld; + GDHandle saveDevice; + GWorldPtr destPort; + const BitMap *destBitMap; + RGBColor origForeColor, origBackColor, foreColor, backColor; + + HLock(sicnHandle); + destPort = TkMacOSXGetDrawablePort(d); + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + TkMacOSXSetUpClippingRgn(d); + TkMacOSXSetUpGraphicsPort(gc, destPort); + GetForeColor(&origForeColor); + GetBackColor(&origBackColor); + + if (TkSetMacColor(gc->foreground, &foreColor)) { + RGBForeColor(&foreColor); + } + + if (TkSetMacColor(gc->background, &backColor)) { + RGBBackColor(&backColor); + } + + SetRect(&destRect, x, y, x + SICN_HEIGHT, y + SICN_HEIGHT); + sicnBitmap.baseAddr = (Ptr) (*sicnHandle) + index * SICN_HEIGHT + * SICN_ROWS; + sicnBitmap.rowBytes = SICN_ROWS; + SetRect(&sicnBitmap.bounds, 0, 0, 16, 16); + destBitMap = GetPortBitMapForCopyBits(destPort); + CopyBits(&sicnBitmap, destBitMap, &sicnBitmap.bounds, &destRect, GetPortTextMode(destPort), NULL); + HUnlock(sicnHandle); + RGBForeColor(&origForeColor); + RGBBackColor(&origBackColor); + SetGWorld(saveWorld, saveDevice); + return 1; + } +} + +/* + *---------------------------------------------------------------------- + * + * DrawMenuEntryAccelerator -- + * + * This procedure draws the accelerator part of a menu. We + * need to decide what to draw here. Should we replace strings + * like "Control", "Command", etc? + * + * Results: + * None. + * + * Side effects: + * Commands are output to X to display the menu in its + * current mode. + * + *---------------------------------------------------------------------- + */ + +static void +DrawMenuEntryAccelerator( + TkMenu *menuPtr, /* The menu we are drawing */ + TkMenuEntry *mePtr, /* The entry we are drawing */ + Drawable d, /* The drawable we are drawing in */ + GC gc, /* The gc to draw into */ + Tk_Font tkfont, /* The precalculated font */ + CONST Tk_FontMetrics *fmPtr, /* The precalculated font metrics */ + Tk_3DBorder activeBorder, /* border for menu background */ + int x, /* The left side of the entry */ + int y, /* The top of the entry */ + int width, /* The width of the entry */ + int height, /* The height of the entry */ + int drawArrow) /* Whether or not to draw cascade arrow */ +{ + int activeBorderWidth; + + Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr, + &activeBorderWidth); + if (mePtr->type == CASCADE_ENTRY) { + /* + * Under Appearance, we let the Appearance Manager draw the icon + */ + + } else if (mePtr->accelLength != 0) { + int leftEdge = x + width; + int baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2; + char *accel; + + accel = Tcl_GetStringFromObj(mePtr->accelPtr, NULL); + + if (NULL == GetResource('SICN', SICN_RESOURCE_NUMBER)) { + leftEdge -= ((EntryGeometry *) mePtr->platformEntryData) + ->accelTextWidth; + Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel, + mePtr->accelLength, leftEdge, baseline); + } else { + EntryGeometry *geometryPtr = + (EntryGeometry *) mePtr->platformEntryData; + int length = mePtr->accelLength - geometryPtr->accelTextStart; + + leftEdge -= geometryPtr->accelTextWidth; + if ((mePtr->entryFlags & ENTRY_ACCEL_MASK) == 0) { + leftEdge -= geometryPtr->modifierWidth; + } + + Tk_DrawChars(menuPtr->display, d, gc, tkfont, accel + + geometryPtr->accelTextStart, length, leftEdge, baseline); + + if (mePtr->entryFlags & ENTRY_COMMAND_ACCEL) { + leftEdge -= COMMAND_ICON_WIDTH; + DrawSICN(SICN_RESOURCE_NUMBER, COMMAND_ICON, d, gc, + leftEdge, (y + (height / 2)) - (SICN_HEIGHT / 2) - 1); + } + + if (mePtr->entryFlags & ENTRY_OPTION_ACCEL) { + leftEdge -= OPTION_ICON_WIDTH; + DrawSICN(SICN_RESOURCE_NUMBER, OPTION_ICON, d, gc, + leftEdge, (y + (height / 2)) - (SICN_HEIGHT / 2) - 1); + } + + if (mePtr->entryFlags & ENTRY_SHIFT_ACCEL) { + leftEdge -= SHIFT_ICON_WIDTH; + DrawSICN(SICN_RESOURCE_NUMBER, SHIFT_ICON, d, gc, + leftEdge, (y + (height / 2)) - (SICN_HEIGHT / 2) - 1); + } + + if (mePtr->entryFlags & ENTRY_CONTROL_ACCEL) { + leftEdge -= CONTROL_ICON_WIDTH; + DrawSICN(SICN_RESOURCE_NUMBER, CONTROL_ICON, d, gc, + leftEdge, (y + (height / 2)) - (SICN_HEIGHT / 2) - 1); + } + } + } +} + +/* + *---------------------------------------------------------------------- + * + * DrawMenuSeparator -- + * + * The menu separator is drawn. + * + * Results: + * None. + * + * Side effects: + * Commands are output to X to display the menu in its + * current mode. + * + *---------------------------------------------------------------------- + */ + +static void +DrawMenuSeparator( + TkMenu *menuPtr, /* The menu we are drawing */ + TkMenuEntry *mePtr, /* The entry we are drawing */ + Drawable d, /* The drawable we are drawing into */ + GC gc, /* The gc we are drawing with */ + Tk_Font tkfont, /* The precalculated font */ + CONST Tk_FontMetrics *fmPtr, /* The precalculated font metrics */ + int x, /* left coordinate of entry */ + int y, /* top coordinate of entry */ + int width, /* width of entry */ + int height) /* height of entry */ +{ + CGrafPtr saveWorld; + GDHandle saveDevice; + GWorldPtr destPort; + Rect r; + + destPort = TkMacOSXGetDrawablePort(d); + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + TkMacOSXSetUpClippingRgn(d); + r.top = y; + r.left = x; + r.bottom = y + height; + r.right = x + width; + + DrawThemeMenuSeparator(&r); +} + +/* + *---------------------------------------------------------------------- + * + * AppearanceEntryDrawWrapper -- + * + * It routes to the Appearance Managers DrawThemeEntry, which will + * then call us back after setting up the drawing context. + * + * Results: + * A menu entry is drawn + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ +static void +AppearanceEntryDrawWrapper( + TkMenuEntry *mePtr, + Rect *menuRectPtr, + MenuTrackingData *mtdPtr, + Drawable d, + Tk_FontMetrics *fmPtr, + Tk_Font tkfont, + int x, + int y, + int width, + int height) +{ + MenuEntryUserData meData; + Rect itemRect; + ThemeMenuState theState; + ThemeMenuItemType theType; + + meData.mePtr = mePtr; + meData.mdefDrawable = d; + meData.fmPtr = fmPtr; + meData.tkfont = tkfont; + + itemRect.top = y; + itemRect.left = x; + itemRect.bottom = itemRect.top + height; + itemRect.right = itemRect.left + width; + + if (mePtr->state == ENTRY_ACTIVE) { + theState = kThemeMenuSelected; + } else if (mePtr->state == ENTRY_DISABLED) { + theState = kThemeMenuDisabled; + } else { + theState = kThemeMenuActive; + } + + if (mePtr->type == CASCADE_ENTRY) { + theType = kThemeMenuItemHierarchical; + } else { + theType = kThemeMenuItemPlain; + } + + DrawThemeMenuItem (menuRectPtr, &itemRect, + mtdPtr->virtualMenuTop, mtdPtr->virtualMenuBottom, theState, + theType, tkThemeMenuItemDrawingUPP, + (unsigned long) &meData); + +} + +/* + *---------------------------------------------------------------------- + * + * tkThemeMenuItemDrawingProc -- + * + * This routine is called from the Appearance DrawThemeMenuEntry + * + * Results: + * A menu entry is drawn + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ +pascal void +tkThemeMenuItemDrawingProc ( + const Rect *inBounds, + SInt16 inDepth, + Boolean inIsColorDevice, + SInt32 inUserData) +{ + MenuEntryUserData *meData = (MenuEntryUserData *) inUserData; + TkpDrawMenuEntry(meData->mePtr, meData->mdefDrawable, + meData->tkfont, meData->fmPtr, inBounds->left, + inBounds->top, inBounds->right - inBounds->left, + inBounds->bottom - inBounds->top, 0, 1); +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXHandleTearoffMenu() -- + * + * This routine sees if the MDEF has set a menu and a mouse position + * for tearing off and makes a tearoff menu if it has. + * + * Results: + * menuPtr->interp will have the result of the tearoff command. + * + * Side effects: + * A new tearoff menu is created if it is supposed to be. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXHandleTearoffMenu(void) +{ + if (tearoffStruct.menuPtr != NULL) { + Tcl_DString tearoffCmdStr; + char intString[TCL_INTEGER_SPACE]; + short windowPart; + WindowRef whichWindow; + + windowPart = FindWindow(tearoffStruct.point, &whichWindow); + + if (windowPart != inMenuBar) { + Tcl_DStringInit(&tearoffCmdStr); + Tcl_DStringAppendElement(&tearoffCmdStr, "tkTearOffMenu"); + Tcl_DStringAppendElement(&tearoffCmdStr, + Tk_PathName(tearoffStruct.menuPtr->tkwin)); + sprintf(intString, "%d", tearoffStruct.point.h); + Tcl_DStringAppendElement(&tearoffCmdStr, intString); + sprintf(intString, "%d", tearoffStruct.point.v); + Tcl_DStringAppendElement(&tearoffCmdStr, intString); + Tcl_Eval(tearoffStruct.menuPtr->interp, + Tcl_DStringValue(&tearoffCmdStr)); + Tcl_DStringFree(&tearoffCmdStr); + tearoffStruct.menuPtr = NULL; + } + } +} + +/* + *-------------------------------------------------------------- + * + * TkpInitializeMenuBindings -- + * + * For every interp, initializes the bindings for Windows + * menus. Does nothing on Mac or XWindows. + * + * Results: + * None. + * + * Side effects: + * C-level bindings are setup for the interp which will + * handle Alt-key sequences for menus without beeping + * or interfering with user-defined Alt-key bindings. + * + *-------------------------------------------------------------- + */ + +void +TkpInitializeMenuBindings(interp, bindingTable) + Tcl_Interp *interp; /* The interpreter to set. */ + Tk_BindingTable bindingTable; /* The table to add to. */ +{ + /* + * Nothing to do. + */ +} + +/* + *-------------------------------------------------------------- + * + * TkpComputeMenubarGeometry -- + * + * This procedure is invoked to recompute the size and + * layout of a menu that is a menubar clone. + * + * Results: + * None. + * + * Side effects: + * Fields of menu entries are changed to reflect their + * current positions, and the size of the menu window + * itself may be changed. + * + *-------------------------------------------------------------- + */ + +void +TkpComputeMenubarGeometry(menuPtr) + TkMenu *menuPtr; /* Structure describing menu. */ +{ + TkpComputeStandardMenuGeometry(menuPtr); +} + +/* + *---------------------------------------------------------------------- + * + * DrawTearoffEntry -- + * + * This procedure draws the background part of a menu. + * + * Results: + * None. + * + * Side effects: + * Commands are output to X to display the menu in its + * current mode. + * + *---------------------------------------------------------------------- + */ + +void +DrawTearoffEntry( + TkMenu *menuPtr, /* The menu we are drawing */ + TkMenuEntry *mePtr, /* The entry we are drawing */ + Drawable d, /* The drawable we are drawing into */ + GC gc, /* The gc we are drawing with */ + Tk_Font tkfont, /* The font we are drawing with */ + CONST Tk_FontMetrics *fmPtr, /* The metrics we are drawing with */ + int x, /* Left edge of entry. */ + int y, /* Top edge of entry. */ + int width, /* Width of entry. */ + int height) /* Height of entry. */ +{ + XPoint points[2]; + int margin, segmentWidth, maxX; + Tk_3DBorder border; + + if (menuPtr->menuType != MASTER_MENU ) { + return; + } + + margin = (fmPtr->ascent + fmPtr->descent)/2; + points[0].x = x; + points[0].y = y + height/2; + points[1].y = points[0].y; + segmentWidth = 6; + maxX = width - 1; + border = Tk_Get3DBorderFromObj(menuPtr->tkwin, menuPtr->borderPtr); + + while (points[0].x < maxX) { + points[1].x = points[0].x + segmentWidth; + if (points[1].x > maxX) { + points[1].x = maxX; + } + Tk_Draw3DPolygon(menuPtr->tkwin, d, border, points, 2, 1, + TK_RELIEF_RAISED); + points[0].x += 2*segmentWidth; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXSetHelpMenuItemCount -- + * + * Has to be called after the first call to InsertMenu. Sets + * up the global variable for the number of items in the + * unmodified help menu. + * + * Results: + * None. + * + * Side effects: + * Sets the global helpItemCount. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXSetHelpMenuItemCount() +{ + MenuRef helpMenuHandle; + MenuItemIndex itemIndex; + + if ((HMGetHelpMenu(&helpMenuHandle,&itemIndex) != noErr) + || (helpMenuHandle == NULL)) { + helpItemCount = -1; + } else { + helpItemCount = CountMenuItems(helpMenuHandle); + DeleteMenuItem(helpMenuHandle, helpItemCount); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXMenuClick -- + * + * Prepares a menubar for MenuSelect or MenuKey. + * + * Results: + * None. + * + * Side effects: + * Any pending configurations of the menubar are completed. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXMenuClick() +{ + TkMenu *menuPtr; + TkMenuReferences *menuRefPtr; + + if ((currentMenuBarInterp != NULL) && (currentMenuBarName != NULL)) { + menuRefPtr = TkFindMenuReferences(currentMenuBarInterp, + currentMenuBarName); + for (menuPtr = menuRefPtr->menuPtr->masterMenuPtr; + menuPtr != NULL; menuPtr = menuPtr->nextInstancePtr) { + if (menuPtr->menuType == MENUBAR) { + CompleteIdlers(menuPtr); + break; + } + } + } + + if (menuBarFlags & MENUBAR_REDRAW_PENDING) { + Tcl_CancelIdleCall(DrawMenuBarWhenIdle, (ClientData *) NULL); + DrawMenuBarWhenIdle((ClientData *) NULL); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpDrawMenuEntry -- + * + * Draws the given menu entry at the given coordinates with the + * given attributes. + * + * Results: + * None. + * + * Side effects: + * X Server commands are executed to display the menu entry. + * + *---------------------------------------------------------------------- + */ + +void +TkpDrawMenuEntry( + TkMenuEntry *mePtr, /* The entry to draw */ + Drawable d, /* What to draw into */ + Tk_Font tkfont, /* Precalculated font for menu */ + CONST Tk_FontMetrics *menuMetricsPtr, + /* Precalculated metrics for menu */ + int x, /* X-coordinate of topleft of entry */ + int y, /* Y-coordinate of topleft of entry */ + int width, /* Width of the entry rectangle */ + int height, /* Height of the current rectangle */ + int strictMotif, /* Boolean flag */ + int drawArrow) /* Whether or not to draw the cascade + * arrow for cascade items. Only applies + * to Windows. */ +{ + GC gc; + TkMenu *menuPtr = mePtr->menuPtr; + int padY = (menuPtr->menuType == MENUBAR) ? 3 : 0; + GC indicatorGC; + Tk_3DBorder bgBorder, activeBorder; + const Tk_FontMetrics *fmPtr; + Tk_FontMetrics entryMetrics; + int adjustedY = y + padY; + int adjustedHeight = height - 2 * padY; + + /* + * Choose the gc for drawing the foreground part of the entry. + * Under Appearance, we pass a null (appearanceGC) to tell + * ourselves not to change whatever color the appearance manager has set. + */ + + if ((mePtr->state == ENTRY_ACTIVE) && !strictMotif) { + gc = mePtr->activeGC; + if (gc == NULL) { + gc = menuPtr->activeGC; + } + } else { + TkMenuEntry *cascadeEntryPtr; + int parentDisabled = 0; + + for (cascadeEntryPtr = menuPtr->menuRefPtr->parentEntryPtr; + cascadeEntryPtr != NULL; + cascadeEntryPtr = cascadeEntryPtr->nextCascadePtr) { + char *name = (cascadeEntryPtr->namePtr == NULL) ? "" + : Tcl_GetStringFromObj(cascadeEntryPtr->namePtr, NULL); + + if (strcmp(name, Tk_PathName(menuPtr->tkwin)) == 0) { + if (cascadeEntryPtr->state == ENTRY_DISABLED) { + parentDisabled = 1; + } + break; + } + } + + if (((parentDisabled || (mePtr->state == ENTRY_DISABLED))) + && (menuPtr->disabledFgPtr != NULL)) { + gc = mePtr->disabledGC; + if (gc == NULL) { + gc = menuPtr->disabledGC; + } + } else { + gc = mePtr->textGC; + if (gc == NULL) { + gc = menuPtr->textGC; + } + } + } + + indicatorGC = mePtr->indicatorGC; + if (indicatorGC == NULL) { + indicatorGC = menuPtr->indicatorGC; + } + + bgBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin, + (mePtr->borderPtr == NULL) + ? menuPtr->borderPtr : mePtr->borderPtr); + if (strictMotif) { + activeBorder = bgBorder; + } else { + activeBorder = Tk_Get3DBorderFromObj(menuPtr->tkwin, + (mePtr->activeBorderPtr == NULL) + ? menuPtr->activeBorderPtr : mePtr->activeBorderPtr); + } + + if (mePtr->fontPtr == NULL) { + fmPtr = menuMetricsPtr; + } else { + tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr); + Tk_GetFontMetrics(tkfont, &entryMetrics); + fmPtr = &entryMetrics; + } + + /* + * Need to draw the entire background, including padding. On Unix, + * for menubars, we have to draw the rest of the entry taking + * into account the padding. + */ + + DrawMenuEntryBackground(menuPtr, mePtr, d, activeBorder, + bgBorder, x, y, width, height); + + if (mePtr->type == SEPARATOR_ENTRY) { + DrawMenuSeparator(menuPtr, mePtr, d, gc, tkfont, + fmPtr, x, adjustedY, width, adjustedHeight); + } else if (mePtr->type == TEAROFF_ENTRY) { + DrawTearoffEntry(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, adjustedY, + width, adjustedHeight); + } else { + DrawMenuEntryLabel(menuPtr, mePtr, d, gc, tkfont, fmPtr, x, + adjustedY, width, adjustedHeight); + DrawMenuEntryAccelerator(menuPtr, mePtr, d, gc, tkfont, fmPtr, + activeBorder, x, adjustedY, width, adjustedHeight, drawArrow); + if (!mePtr->hideMargin) { + DrawMenuEntryIndicator(menuPtr, mePtr, d, gc, indicatorGC, tkfont, + fmPtr, x, adjustedY, width, adjustedHeight); + } + + } +} + +/* + *-------------------------------------------------------------- + * + * TkpComputeStandardMenuGeometry -- + * + * This procedure is invoked to recompute the size and + * layout of a menu that is not a menubar clone. + * + * Results: + * None. + * + * Side effects: + * Fields of menu entries are changed to reflect their + * current positions, and the size of the menu window + * itself may be changed. + * + *-------------------------------------------------------------- + */ + +void +TkpComputeStandardMenuGeometry( + TkMenu *menuPtr) /* Structure describing menu. */ +{ + Tk_Font tkfont, menuFont; + Tk_FontMetrics menuMetrics, entryMetrics, *fmPtr; + int x, y, height, modifierWidth, labelWidth, indicatorSpace; + int windowWidth, windowHeight, accelWidth, maxAccelTextWidth; + int i, j, lastColumnBreak, maxModifierWidth, maxWidth, nonAccelMargin; + int maxNonAccelMargin, maxEntryWithAccelWidth, maxEntryWithoutAccelWidth; + int entryWidth, maxIndicatorSpace, borderWidth, activeBorderWidth; + TkMenuEntry *mePtr, *columnEntryPtr; + EntryGeometry *geometryPtr; + + if (menuPtr->tkwin == NULL) { + return; + } + + Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->borderWidthPtr, + &borderWidth); + Tk_GetPixelsFromObj(NULL, menuPtr->tkwin, menuPtr->activeBorderWidthPtr, + &activeBorderWidth); + x = y = borderWidth; + indicatorSpace = labelWidth = accelWidth = maxAccelTextWidth = 0; + windowHeight = windowWidth = maxWidth = lastColumnBreak = 0; + maxModifierWidth = nonAccelMargin = maxNonAccelMargin = 0; + maxEntryWithAccelWidth = maxEntryWithoutAccelWidth = 0; + maxIndicatorSpace = 0; + + /* + * On the Mac especially, getting font metrics can be quite slow, + * so we want to do it intelligently. We are going to precalculate + * them and pass them down to all of the measuring and drawing + * routines. We will measure the font metrics of the menu once. + * If an entry does not have its own font set, then we give + * the geometry/drawing routines the menu's font and metrics. + * If an entry has its own font, we will measure that font and + * give all of the geometry/drawing the entry's font and metrics. + */ + + menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr); + Tk_GetFontMetrics(menuFont, &menuMetrics); + + for (i = 0; i < menuPtr->numEntries; i++) { + mePtr = menuPtr->entries[i]; + if (mePtr->fontPtr == NULL) { + tkfont = menuFont; + fmPtr = &menuMetrics; + } else { + tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr); + Tk_GetFontMetrics(tkfont, &entryMetrics); + fmPtr = &entryMetrics; + } + + if ((i > 0) && mePtr->columnBreak) { + if (maxIndicatorSpace != 0) { + maxIndicatorSpace += 2; + } + for (j = lastColumnBreak; j < i; j++) { + columnEntryPtr = menuPtr->entries[j]; + geometryPtr = + (EntryGeometry *) columnEntryPtr->platformEntryData; + + columnEntryPtr->indicatorSpace = maxIndicatorSpace; + columnEntryPtr->width = maxIndicatorSpace + maxWidth + + 2 * activeBorderWidth; + geometryPtr->accelTextWidth = maxAccelTextWidth; + geometryPtr->modifierWidth = maxModifierWidth; + columnEntryPtr->x = x; + columnEntryPtr->entryFlags &= ~ENTRY_LAST_COLUMN; + if (maxEntryWithoutAccelWidth > maxEntryWithAccelWidth) { + geometryPtr->nonAccelMargin = maxEntryWithoutAccelWidth + - maxEntryWithAccelWidth; + if (geometryPtr->nonAccelMargin > maxNonAccelMargin) { + geometryPtr->nonAccelMargin = maxNonAccelMargin; + } + } else { + geometryPtr->nonAccelMargin = 0; + } + } + x += maxIndicatorSpace + maxWidth + 2 * borderWidth; + windowWidth = x; + maxWidth = maxIndicatorSpace = maxAccelTextWidth = 0; + maxModifierWidth = maxNonAccelMargin = maxEntryWithAccelWidth = 0; + maxEntryWithoutAccelWidth = 0; + lastColumnBreak = i; + y = borderWidth; + } + + if (mePtr->type == SEPARATOR_ENTRY) { + GetMenuSeparatorGeometry(menuPtr, mePtr, tkfont, + fmPtr, &entryWidth, &height); + mePtr->height = height; + } else if (mePtr->type == TEAROFF_ENTRY) { + GetTearoffEntryGeometry(menuPtr, mePtr, tkfont, + fmPtr, &entryWidth, &height); + mePtr->height = height; + } else { + /* + * For each entry, compute the height required by that + * particular entry, plus three widths: the width of the + * label, the width to allow for an indicator to be displayed + * to the left of the label (if any), and the width of the + * accelerator to be displayed to the right of the label + * (if any). These sizes depend, of course, on the type + * of the entry. + */ + + GetMenuLabelGeometry(mePtr, tkfont, fmPtr, &labelWidth, + &height); + mePtr->height = height; + + if (mePtr->type == CASCADE_ENTRY) { + GetMenuAccelGeometry(menuPtr, mePtr, tkfont, fmPtr, + &modifierWidth, &accelWidth, &height); + nonAccelMargin = 0; + } else if (mePtr->accelLength == 0) { + nonAccelMargin = mePtr->hideMargin ? 0 + : Tk_TextWidth(tkfont, "m", 1); + accelWidth = modifierWidth = 0; + } else { + labelWidth += Tk_TextWidth(tkfont, "m", 1); + GetMenuAccelGeometry(menuPtr, mePtr, tkfont, + fmPtr, &modifierWidth, &accelWidth, &height); + if (height > mePtr->height) { + mePtr->height = height; + } + nonAccelMargin = 0; + } + + if (!(mePtr->hideMargin)) { + GetMenuIndicatorGeometry(menuPtr, mePtr, tkfont, + fmPtr, &indicatorSpace, &height); + if (height > mePtr->height) { + mePtr->height = height; + } + } else { + indicatorSpace = 0; + } + + if (nonAccelMargin > maxNonAccelMargin) { + maxNonAccelMargin = nonAccelMargin; + } + if (accelWidth > maxAccelTextWidth) { + maxAccelTextWidth = accelWidth; + } + if (modifierWidth > maxModifierWidth) { + maxModifierWidth = modifierWidth; + } + if (indicatorSpace > maxIndicatorSpace) { + maxIndicatorSpace = indicatorSpace; + } + + entryWidth = labelWidth + modifierWidth + accelWidth + + nonAccelMargin; + + if (entryWidth > maxWidth) { + maxWidth = entryWidth; + } + + if (mePtr->accelLength > 0) { + if (entryWidth > maxEntryWithAccelWidth) { + maxEntryWithAccelWidth = entryWidth; + } + } else { + if (entryWidth > maxEntryWithoutAccelWidth) { + maxEntryWithoutAccelWidth = entryWidth; + } + } + + mePtr->height += 2 * activeBorderWidth; + } + mePtr->y = y; + y += menuPtr->entries[i]->height + borderWidth; + if (y > windowHeight) { + windowHeight = y; + } + } + + for (j = lastColumnBreak; j < menuPtr->numEntries; j++) { + columnEntryPtr = menuPtr->entries[j]; + geometryPtr = (EntryGeometry *) columnEntryPtr->platformEntryData; + + columnEntryPtr->indicatorSpace = maxIndicatorSpace; + columnEntryPtr->width = maxIndicatorSpace + maxWidth + + 2 * activeBorderWidth; + geometryPtr->accelTextWidth = maxAccelTextWidth; + geometryPtr->modifierWidth = maxModifierWidth; + columnEntryPtr->x = x; + columnEntryPtr->entryFlags |= ENTRY_LAST_COLUMN; + if (maxEntryWithoutAccelWidth > maxEntryWithAccelWidth) { + geometryPtr->nonAccelMargin = maxEntryWithoutAccelWidth + - maxEntryWithAccelWidth; + if (geometryPtr->nonAccelMargin > maxNonAccelMargin) { + geometryPtr->nonAccelMargin = maxNonAccelMargin; + } + } else { + geometryPtr->nonAccelMargin = 0; + } + } + windowWidth = x + maxIndicatorSpace + maxWidth + + 2 * activeBorderWidth + borderWidth; + windowHeight += borderWidth; + + /* + * The X server doesn't like zero dimensions, so round up to at least + * 1 (a zero-sized menu should never really occur, anyway). + */ + + if (windowWidth <= 0) { + windowWidth = 1; + } + if (windowHeight <= 0) { + windowHeight = 1; + } + menuPtr->totalWidth = windowWidth; + menuPtr->totalHeight = windowHeight; +} + +/* + *---------------------------------------------------------------------- + * + * DrawMenuEntryLabel -- + * + * This procedure draws the label part of a menu. + * + * Results: + * None. + * + * Side effects: + * Commands are output to X to display the menu in its + * current mode. + * + *---------------------------------------------------------------------- + */ + +static void +DrawMenuEntryLabel( + TkMenu *menuPtr, /* The menu we are drawing */ + TkMenuEntry *mePtr, /* The entry we are drawing */ + Drawable d, /* What we are drawing into */ + GC gc, /* The gc we are drawing into */ + Tk_Font tkfont, /* The precalculated font */ + CONST Tk_FontMetrics *fmPtr, /* The precalculated font metrics */ + int x, /* left edge */ + int y, /* right edge */ + int width, /* width of entry */ + int height) /* height of entry */ +{ + int baseline; + int indicatorSpace = mePtr->indicatorSpace; + int leftEdge = x + indicatorSpace; + int imageHeight, imageWidth; + + /* + * Draw label or bitmap or image for entry. + */ + + baseline = y + (height + fmPtr->ascent - fmPtr->descent) / 2; + if (mePtr->image != NULL) { + Tk_SizeOfImage(mePtr->image, &imageWidth, &imageHeight); + if ((mePtr->selectImage != NULL) + && (mePtr->entryFlags & ENTRY_SELECTED)) { + Tk_RedrawImage(mePtr->selectImage, 0, 0, + imageWidth, imageHeight, d, leftEdge, + (int) (y + (mePtr->height - imageHeight)/2)); + } else { + Tk_RedrawImage(mePtr->image, 0, 0, imageWidth, + imageHeight, d, leftEdge, + (int) (y + (mePtr->height - imageHeight)/2)); + } + } else if (mePtr->bitmapPtr != NULL) { + int width, height; + Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr); + Tk_SizeOfBitmap(menuPtr->display, + bitmap, &width, &height); + XCopyPlane(menuPtr->display, bitmap, d, gc, 0, 0, + (unsigned) width, (unsigned) height, leftEdge, + (int) (y + (mePtr->height - height)/2), 1); + } else { + if (mePtr->labelLength > 0) { + Tcl_DString itemTextDString, convertedTextDString; + CGrafPtr saveWorld; + GDHandle saveDevice; + GWorldPtr destPort; +#ifdef USE_ATSU + int runLengths; + CFStringRef stringRef; + ATSUTextLayout textLayout; + UniCharCount runLength; + ATSUStyle style; + int length; + int err; + Str255 fontName; + SInt16 fontSize; + Style fontStyle; + ATSUAttributeValuePtr valuePtr; + ByteCount valueSize; + Fixed fixedSize; + short iFONDNumber; + ATSUFontID fontID; + ATSUAttributeTag tag; + + GetThemeFont (kThemeMenuItemFont, smSystemScript, fontName, &fontSize, &fontStyle); + if ((err = ATSUCreateStyle(&style)) != noErr) { + fprintf(stderr,"ATSUCreateStyle failed, %d\n", err); + return; + } + fixedSize = fontSize<<16; + tag = kATSUSizeTag; + valueSize = sizeof(fixedSize); + valuePtr = &fixedSize; + if ((err=ATSUSetAttributes(style, 1, &tag, &valueSize, &valuePtr))!= noErr) { + fprintf(stderr,"ATSUSetAttributes failed,%d\n", err ); + } + + GetFNum(fontName, &iFONDNumber); + ATSUFONDtoFontID(iFONDNumber, NULL, &fontID); + tag = kATSUFontTag; + valueSize = sizeof(fontID); + valuePtr = &fontID; + if ((err=ATSUSetAttributes(style, 1, &tag, &valueSize, &valuePtr))!= noErr) { + fprintf(stderr,"ATSUSetAttributes failed,%d\n", err ); + } + +#endif + + GetEntryText(mePtr, &itemTextDString); +#ifdef USE_ATSU + runLengths = 1; + length = Tcl_DStringLength(&itemTextDString); + stringRef = CFStringCreateWithCString(NULL, Tcl_DStringValue(&itemTextDString), GetApplicationTextEncoding()); + if (!stringRef) { + fprintf(stderr,"CFStringCreateWithCString failed\n"); + } + if ((err=ATSUCreateTextLayoutWithTextPtr(CFStringGetCharactersPtr(stringRef), 0, length, length, + 1, &runLengths, &style, &textLayout)) != noErr) { + fprintf(stderr,"ATSUCreateTextLayoutWithTextPtr failed, %d\n", err); + return; + } +#endif + + /* Somehow DrawChars is changing the colors, it is odd, since + it works for the Apple Platinum Appearance, but not for + some Kaleidoscope Themes... Untill I can figure out what + exactly is going on, this will have to do: */ + + destPort = TkMacOSXGetDrawablePort(d); + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + TkMacOSXSetUpGraphicsPort(gc, destPort); + + MoveTo((short) leftEdge, (short) baseline); + Tcl_UtfToExternalDString(NULL, Tcl_DStringValue(&itemTextDString), + Tcl_DStringLength(&itemTextDString), &convertedTextDString); +#ifdef USE_ATSU + xLocation = leftEdge<<16; + yLocation = baseline<<16; + ATSUDrawText(textLayout,kATSUFromTextBeginning, kATSUToTextEnd, xLocation, yLocation); + ATSUDisposeTextLayout(textLayout); + CFRelease(stringRef); +#else + DrawText(Tcl_DStringValue(&convertedTextDString), 0, + Tcl_DStringLength(&convertedTextDString)); +#endif + + /* Tk_DrawChars(menuPtr->display, d, gc, + tkfont, Tcl_DStringValue(&itemTextDString), + Tcl_DStringLength(&itemTextDString), + leftEdge, baseline); */ + + Tcl_DStringFree(&itemTextDString); + } + } + + if (mePtr->state == ENTRY_DISABLED) { + if (menuPtr->disabledFgPtr == NULL) { + } else if ((mePtr->image != NULL) + && (menuPtr->disabledImageGC != None)) { + XFillRectangle(menuPtr->display, d, menuPtr->disabledImageGC, + leftEdge, + (int) (y + (mePtr->height - imageHeight)/2), + (unsigned) imageWidth, (unsigned) imageHeight); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * DrawMenuEntryBackground -- + * + * This procedure draws the background part of a menu entry. + * Under Appearance, we only draw the background if the entry's + * border is set, we DO NOT inherit it from the menu... + * + * Results: + * None. + * + * Side effects: + * Commands are output to X to display the menu in its + * current mode. + * + *---------------------------------------------------------------------- + */ + +static void +DrawMenuEntryBackground( + TkMenu *menuPtr, /* The menu we are drawing. */ + TkMenuEntry *mePtr, /* The entry we are drawing. */ + Drawable d, /* What we are drawing into */ + Tk_3DBorder activeBorder, /* Border for active items */ + Tk_3DBorder bgBorder, /* Border for the background */ + int x, /* left edge */ + int y, /* top edge */ + int width, /* width of rectangle to draw */ + int height) /* height of rectangle to draw */ +{ + if ((menuPtr->menuType == TEAROFF_MENU) + || ((mePtr->state == ENTRY_ACTIVE) + && (mePtr->activeBorderPtr != None)) + || ((mePtr->state != ENTRY_ACTIVE) && (mePtr->borderPtr != None))) { + if (mePtr->state == ENTRY_ACTIVE) { + bgBorder = activeBorder; + } + Tk_Fill3DRectangle(menuPtr->tkwin, d, bgBorder, + x, y, width, height, 0, TK_RELIEF_FLAT); + } +} + +/* + *---------------------------------------------------------------------- + * + * GetMenuLabelGeometry -- + * + * Figures out the size of the label portion of a menu item. + * + * Results: + * widthPtr and heightPtr are filled in with the correct geometry + * information. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +GetMenuLabelGeometry( + TkMenuEntry *mePtr, /* The entry we are computing */ + Tk_Font tkfont, /* The precalculated font */ + CONST Tk_FontMetrics *fmPtr, /* The precalculated metrics */ + int *widthPtr, /* The resulting width of the label + * portion */ + int *heightPtr) /* The resulting height of the label + * portion */ +{ + TkMenu *menuPtr = mePtr->menuPtr; + + if (mePtr->image != NULL) { + Tk_SizeOfImage(mePtr->image, widthPtr, heightPtr); + } else if (mePtr->bitmapPtr != NULL) { + Pixmap bitmap = Tk_GetBitmapFromObj(menuPtr->tkwin, mePtr->bitmapPtr); + Tk_SizeOfBitmap(menuPtr->display, bitmap, widthPtr, heightPtr); + } else { + *heightPtr = fmPtr->linespace; + + if (mePtr->labelPtr != NULL) { + Tcl_DString itemTextDString; + + GetEntryText(mePtr, &itemTextDString); + *widthPtr = Tk_TextWidth(tkfont, + Tcl_DStringValue(&itemTextDString), + Tcl_DStringLength(&itemTextDString)); + Tcl_DStringFree(&itemTextDString); + } else { + *widthPtr = 0; + } + } + *heightPtr += 1; +} + +/* + *---------------------------------------------------------------------- + * + * MenuSelectEvent -- + * + * Generates a "MenuSelect" virtual event. This can be used to + * do context-sensitive menu help. + * + * Results: + * None. + * + * Side effects: + * Places a virtual event on the event queue. + * + *---------------------------------------------------------------------- + */ + +static void +MenuSelectEvent( + TkMenu *menuPtr) /* the menu we have selected. */ +{ + XVirtualEvent event; + Point where; + CGrafPtr port; + Rect bounds; + + event.type = VirtualEvent; + event.serial = menuPtr->display->request; + event.send_event = false; + event.display = menuPtr->display; + Tk_MakeWindowExist(menuPtr->tkwin); + event.event = Tk_WindowId(menuPtr->tkwin); + event.root = XRootWindow(menuPtr->display, 0); + event.subwindow = None; + event.time = TkpGetMS(); + + GetMouse(&where); + GetPort(&port); + GetPortBounds(port,&bounds); + event.x_root = where.h + bounds.left; + event.y_root = where.v + bounds.top; + event.state = TkMacOSXButtonKeyState(); + event.same_screen = true; + event.name = Tk_GetUid("MenuSelect"); + Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL); +} + +/* + *---------------------------------------------------------------------- + * + * RecursivelyClearActiveMenu -- + * + * Recursively clears the active entry in the menu's cascade hierarchy. + * + * Results: + * None. + * + * Side effects: + * Generates <<MenuSelect>> virtual events. + * + *---------------------------------------------------------------------- + */ + +void +RecursivelyClearActiveMenu( + TkMenu *menuPtr) /* The menu to reset. */ +{ + int i; + TkMenuEntry *mePtr; + + TkActivateMenuEntry(menuPtr, -1); + MenuSelectEvent(menuPtr); + for (i = 0; i < menuPtr->numEntries; i++) { + mePtr = menuPtr->entries[i]; + if (mePtr->type == CASCADE_ENTRY) { + if ((mePtr->childMenuRefPtr != NULL) + && (mePtr->childMenuRefPtr->menuPtr != NULL)) { + RecursivelyClearActiveMenu(mePtr->childMenuRefPtr->menuPtr); + } + } + } +} + +/* + *---------------------------------------------------------------------- + * + * InvalidateMDEFRgns -- + * + * Invalidates the regions covered by menus that did redrawing and + * might be damaged. + * + * Results: + * None. + * + * Side effects: + * Generates Mac update events for affected windows. + * + *---------------------------------------------------------------------- + */ + +void +InvalidateMDEFRgns(void) +{ + GDHandle saveDevice; + GWorldPtr saveWorld, destPort; + Point scratch; + MacDrawable *macDraw; + TkMacOSXWindowList *listPtr; + + if (totalMenuRgn == NULL) { + return; + } + + GetGWorld(&saveWorld, &saveDevice); + for (listPtr = tkMacOSXWindowListPtr ; listPtr != NULL; + listPtr = listPtr->nextPtr) { + macDraw = (MacDrawable *) Tk_WindowId(listPtr->winPtr); + if (macDraw->flags & TK_DRAWN_UNDER_MENU) { + destPort = TkMacOSXGetDrawablePort(Tk_WindowId(listPtr->winPtr)); + SetGWorld(destPort, NULL); + scratch.h = scratch.v = 0; + GlobalToLocal(&scratch); + OffsetRgn(totalMenuRgn, scratch.v, scratch.h); + InvalWindowRgn(GetWindowFromPort(destPort),totalMenuRgn); + OffsetRgn(totalMenuRgn, -scratch.v, -scratch.h); + macDraw->flags &= ~TK_DRAWN_UNDER_MENU; + } + } + + SetGWorld(saveWorld, saveDevice); + SetEmptyRgn(totalMenuRgn); +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXClearMenubarActive -- + * + * Recursively clears the active entry in the current menubar hierarchy. + * + * Results: + * None. + * + * Side effects: + * Generates <<MenuSelect>> virtual events. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXClearMenubarActive(void) +{ + TkMenuReferences *menuBarRefPtr; + + if (currentMenuBarName != NULL) { + menuBarRefPtr = TkFindMenuReferences(currentMenuBarInterp, + currentMenuBarName); + if ((menuBarRefPtr != NULL) && (menuBarRefPtr->menuPtr != NULL)) { + TkMenu *menuPtr; + + for (menuPtr = menuBarRefPtr->menuPtr->masterMenuPtr; menuPtr != NULL; + menuPtr = menuPtr->nextInstancePtr) { + if (menuPtr->menuType == MENUBAR) { + RecursivelyClearActiveMenu(menuPtr); + } + } + } + } + InvalidateMDEFRgns(); +} + +/* + *---------------------------------------------------------------------- + * + * TkpMenuNotifyToplevelCreate -- + * + * This routine reconfigures the menu and the clones indicated by + * menuName becuase a toplevel has been created and any system + * menus need to be created. Only applicable to Windows. + * + * Results: + * None. + * + * Side effects: + * An idle handler is set up to do the reconfiguration. + * + *---------------------------------------------------------------------- + */ + +void +TkpMenuNotifyToplevelCreate( + Tcl_Interp *interp, /* The interp the menu lives in. */ + char *menuName) /* The name of the menu to + * reconfigure. */ +{ + /* + * Nothing to do. + */ +} + +/* + *---------------------------------------------------------------------- + * + * TkpMenuInit -- + * + * Initializes Mac-specific menu data. + * + * Results: + * None. + * + * Side effects: + * Allocates a hash table. + * + *---------------------------------------------------------------------- + */ + +void +TkpMenuInit(void) +{ + lastMenuID = 256; + Tcl_InitHashTable(&commandTable, TCL_ONE_WORD_KEYS); + currentMenuBarOwner = NULL; + tearoffStruct.menuPtr = NULL; + currentAppleMenuID = 0; + currentHelpMenuID = 0; + currentMenuBarInterp = NULL; + currentMenuBarName = NULL; + windowListPtr = NULL; + + tkThemeMenuItemDrawingUPP + = NewMenuItemDrawingUPP(tkThemeMenuItemDrawingProc); + + /* + * We should just hardcode the utf-8 ellipsis character into + * 'elipsisString' here + */ + Tcl_ExternalToUtf(NULL, Tcl_GetEncoding(NULL, "macRoman"), + "\311", /* ellipsis character */ + -1, 0, NULL, elipsisString, + TCL_UTF_MAX + 1, NULL, NULL, NULL); + + useMDEFVar = Tcl_NewStringObj("::tk::mac::useCustomMDEF", -1); +} + +/* + *---------------------------------------------------------------------- + * + * TkpMenuThreadInit -- + * + * Does platform-specific initialization of thread-specific + * menu state. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkpMenuThreadInit() +{ + /* + * Nothing to do. + */ +} + +/* + *---------------------------------------------------------------------- + * + * TkpPreprocessMacMenu -- + * + * Handle preprocessing of menubar if it exists. + * + * Results: + * None. + * + * Side effects: + * All post commands for the current menubar get executed. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXPreprocessMenu() +{ + TkMenuReferences *mbRefPtr; + int code; + + if ((currentMenuBarName != NULL) && (currentMenuBarInterp != NULL)) { + mbRefPtr = TkFindMenuReferences(currentMenuBarInterp, + currentMenuBarName); + if ((mbRefPtr != NULL) && (mbRefPtr->menuPtr != NULL)) { + Tcl_Preserve((ClientData)currentMenuBarInterp); + code = TkPreprocessMenu(mbRefPtr->menuPtr->masterMenuPtr); + if ((code != TCL_OK) && (code != TCL_CONTINUE) + && (code != TCL_BREAK)) { + Tcl_AddErrorInfo(currentMenuBarInterp, + "\n (menu preprocess)"); + Tcl_BackgroundError(currentMenuBarInterp); + } + Tcl_Release((ClientData)currentMenuBarInterp); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * MenuDefProc -- + * + * This routine is the MDEF handler for Tk. It receives all messages + * for the menu and dispatches them. + * + * Results: + * None. + * + * Side effects: + * This routine causes menus to be drawn and will certainly allocate + * memory as a result. Also, the menu can scroll up and down, and + * various other interface actions can take place. + * + *---------------------------------------------------------------------- + */ + +static void +MenuDefProc( + SInt16 message, /* What action are we taking? */ + MenuRef menu, /* The menu we are working with */ + Rect *menuRectPtr, /* A pointer to the rect for the + * whole menu. */ + Point hitPt, /* Where the mouse was clicked for + * the appropriate messages. */ + SInt16 *whichItem) /* Output result. Which item was + * hit by the user? */ +{ + TkMenu *menuPtr; + Tcl_HashEntry *commandEntryPtr; + int maxMenuHeight; + MenuID menuID; + BitMap screenBits; + + menuID = GetMenuID(menu); + commandEntryPtr = Tcl_FindHashEntry(&commandTable, (char *) ((int)menuID)); + + if (commandEntryPtr) { + menuPtr = (TkMenu *) Tcl_GetHashValue(commandEntryPtr); + } else { + menuPtr = NULL; + } + + switch (message) { + case kMenuInitMsg: + *whichItem = noErr; + break; + case kMenuDisposeMsg: + break; + case kMenuHiliteItemMsg: { + HandleMenuHiliteMsg (menu, menuRectPtr, hitPt, whichItem, menuPtr); + break; + } + case kMenuCalcItemMsg: + HandleMenuCalcItemMsg (menu, menuRectPtr, hitPt, whichItem, menuPtr); + break; + case kMenuDrawItemsMsg: { + /* + * We do nothing here, because we don't support the Menu Managers + * dynamic item groups + */ + + break; + } + case kMenuThemeSavvyMsg: + *whichItem = kThemeSavvyMenuResponse; + break; + case kMenuSizeMsg: + GetQDGlobalsScreenBits(&screenBits); + maxMenuHeight = screenBits.bounds.bottom + - screenBits.bounds.top + - GetMBarHeight() - SCREEN_MARGIN; + SetMenuWidth(menu, menuPtr->totalWidth ); + SetMenuHeight(menu,maxMenuHeight < menuPtr->totalHeight ? maxMenuHeight : menuPtr->totalHeight ); + break; + case kMenuDrawMsg: + HandleMenuDrawMsg (menu, menuRectPtr, hitPt, whichItem, menuPtr); + break; + case kMenuFindItemMsg: + HandleMenuFindItemsMsg (menu, menuRectPtr, hitPt, whichItem, menuPtr); + break; + case kMenuPopUpMsg: + HandleMenuPopUpMsg (menu, menuRectPtr, hitPt, whichItem, menuPtr); + break; + } +} + +void +HandleMenuHiliteMsg (MenuRef menu, + Rect *menuRectPtr, + Point hitPt, + SInt16 *whichItem, + TkMenu *menuPtr) +{ + TkMenuEntry *mePtr = NULL; + Tk_Font tkfont; + Tk_FontMetrics fontMetrics; + int oldItem; + int newItem = -1; + MDEFHiliteItemData * hidPtr = ( MDEFHiliteItemData *)whichItem; + MenuTrackingData mtd, *mtdPtr = &mtd; + int err; + oldItem = hidPtr->previousItem - 1; + newItem = hidPtr->newItem - 1; + + err = GetMenuTrackingData(menu, mtdPtr); + if (err !=noErr) { + fprintf(stderr,"GetMenuTrackingData failed : %d\n", err ); + return; + } + + if (oldItem >= 0) { + Rect oldItemRect; + int width; + + mePtr = menuPtr->entries[oldItem]; + if (mePtr->fontPtr == NULL) { + tkfont = Tk_GetFontFromObj(menuPtr->tkwin, + menuPtr->fontPtr); + } else { + tkfont = Tk_GetFontFromObj(menuPtr->tkwin, + mePtr->fontPtr); + } + Tk_GetFontMetrics(tkfont, &fontMetrics); + + width = (mePtr->entryFlags & ENTRY_LAST_COLUMN) + ? menuPtr->totalWidth - mePtr->x : mePtr->width; + + /* + * In Aqua, have to call EraseMenuBackground when you overdraw + * a previously selected menu item, otherwise you will see the + * old select highlight under the transparency of the new menu item. + */ + + oldItemRect.left = menuRectPtr->left + mePtr->x; + oldItemRect.right = oldItemRect.left +width; + oldItemRect.top = mtdPtr->virtualMenuTop + mePtr->y; + oldItemRect.bottom = oldItemRect.top + mePtr->height; + + EraseMenuBackground(menu, & oldItemRect, NULL); + + AppearanceEntryDrawWrapper(mePtr, menuRectPtr, mtdPtr, + (Drawable) &macMDEFDrawable, &fontMetrics, tkfont, + oldItemRect.left, + oldItemRect.top, + width, + mePtr->height); + } + if (newItem != -1) { + mePtr = menuPtr->entries[newItem]; + if (mePtr->state != ENTRY_DISABLED) { + TkActivateMenuEntry(menuPtr, newItem); + } + if (mePtr->fontPtr == NULL) { + tkfont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr); + } else { + tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr); + } + Tk_GetFontMetrics(tkfont, &fontMetrics); + AppearanceEntryDrawWrapper(mePtr, menuRectPtr, mtdPtr, + (Drawable) &macMDEFDrawable, &fontMetrics, tkfont, + menuRectPtr->left + mePtr->x, + mtdPtr->virtualMenuTop + mePtr->y, + (mePtr->entryFlags & ENTRY_LAST_COLUMN) ? + menuPtr->totalWidth - mePtr->x : mePtr->width, + mePtr->height); + } + tkUseMenuCascadeRgn = 1; + MenuSelectEvent(menuPtr); + Tcl_ServiceAll(); + tkUseMenuCascadeRgn = 0; + if (newItem!=-1 && mePtr->state != ENTRY_DISABLED) { + TkActivateMenuEntry(menuPtr, -1); + } + +} + +/* + *---------------------------------------------------------------------- + * + * HandleMenuDrawMsg -- + * + * It handles the MenuDefProc's draw message. + * + * Results: + * A menu entry is drawn + * + * Side effects: + * None + * + *---------------------------------------------------------------------- + */ +void +HandleMenuDrawMsg(MenuRef menu, + Rect *menuRectPtr, + Point hitPt, + SInt16 *whichItem, + TkMenu *menuPtr) +{ + Tk_Font tkfont, menuFont; + Tk_FontMetrics fontMetrics, entryMetrics; + Tk_FontMetrics *fmPtr; + TkMenuEntry *mePtr; + int i; + GDHandle device; + TkMenu *searchMenuPtr; + Rect menuClipRect; + ThemeMenuType menuType; + MenuTrackingData * mtdPtr = (MenuTrackingData *)whichItem; + /* + * Store away the menu rectangle so we can keep track of the + * different regions that the menu obscures. + */ + + ((MacMenu *) menuPtr->platformData)->menuRect = *menuRectPtr; + if (tkMenuCascadeRgn == NULL) { + tkMenuCascadeRgn = NewRgn(); + } + if (utilRgn == NULL) { + utilRgn = NewRgn(); + } + if (totalMenuRgn == NULL) { + totalMenuRgn = NewRgn(); + } + SetEmptyRgn(tkMenuCascadeRgn); + for (searchMenuPtr = menuPtr; searchMenuPtr != NULL; ) { + RectRgn(utilRgn, + &((MacMenu *) searchMenuPtr->platformData)->menuRect); + InsetRgn(utilRgn, -1, -1); + UnionRgn(tkMenuCascadeRgn, utilRgn, tkMenuCascadeRgn); + OffsetRgn(utilRgn, 1, 1); + UnionRgn(tkMenuCascadeRgn, utilRgn, tkMenuCascadeRgn); + + if (searchMenuPtr->menuRefPtr->parentEntryPtr != NULL) { + searchMenuPtr = searchMenuPtr->menuRefPtr + ->parentEntryPtr->menuPtr; + } else { + break; + } + if (searchMenuPtr->menuType == MENUBAR) { + break; + } + } + UnionRgn(totalMenuRgn, tkMenuCascadeRgn, totalMenuRgn); + SetEmptyRgn(utilRgn); + + /* + * Now draw the background if Appearance is present... + */ + + GetGWorld(&macMDEFDrawable.grafPtr, &device); + + if (menuPtr->menuRefPtr->topLevelListPtr != NULL) { + menuType = kThemeMenuTypePullDown; + } else if (menuPtr->menuRefPtr->parentEntryPtr != NULL) { + menuType = kThemeMenuTypeHierarchical; + } else { + menuType = kThemeMenuTypePopUp; + } + + DrawMenuBackground(menuRectPtr, (Drawable) &macMDEFDrawable, menuType); + + /* + * Next, figure out scrolling information. + */ + + menuClipRect = *menuRectPtr; + if ((menuClipRect.bottom - menuClipRect.top) + < menuPtr->totalHeight) { + if (mtdPtr->virtualMenuTop < menuRectPtr->top) { + DrawSICN(SICN_RESOURCE_NUMBER, UP_ARROW, + (Drawable) &macMDEFDrawable, + menuPtr->textGC, + menuRectPtr->left + menuPtr->entries[1]->indicatorSpace, + menuRectPtr->top); + menuClipRect.top += SICN_HEIGHT; + } + if ((mtdPtr->virtualMenuTop + menuPtr->totalHeight) + > menuRectPtr->bottom) { + DrawSICN(SICN_RESOURCE_NUMBER, DOWN_ARROW, + (Drawable) &macMDEFDrawable, + menuPtr->textGC, + menuRectPtr->left + menuPtr->entries[1]->indicatorSpace, + menuRectPtr->bottom - SICN_HEIGHT); + menuClipRect.bottom -= SICN_HEIGHT; + } + GetClip(utilRgn); + } + + /* + * Now, actually draw the menu. Don't draw entries that + * are higher than the top arrow, and don't draw entries + * that are lower than the bottom. + */ + + menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr); + Tk_GetFontMetrics(menuFont, &fontMetrics); + for (i = 0; i < menuPtr->numEntries; i++) { + mePtr = menuPtr->entries[i]; + if (mtdPtr->virtualMenuTop + mePtr->y + mePtr->height + < menuClipRect.top) { + continue; + } else if (mtdPtr->virtualMenuTop + mePtr->y + > menuClipRect.bottom) { + continue; + } + ClipRect(&menuClipRect); + if (mePtr->fontPtr == NULL) { + fmPtr = &fontMetrics; + tkfont = menuFont; + } else { + tkfont = Tk_GetFontFromObj(menuPtr->tkwin, mePtr->fontPtr); + Tk_GetFontMetrics(tkfont, &entryMetrics); + fmPtr = &entryMetrics; + } + AppearanceEntryDrawWrapper(mePtr, menuRectPtr, mtdPtr, + (Drawable) &macMDEFDrawable, fmPtr, tkfont, + menuRectPtr->left + mePtr->x, + mtdPtr->virtualMenuTop + mePtr->y, + (mePtr->entryFlags & ENTRY_LAST_COLUMN) ? + menuPtr->totalWidth - mePtr->x : mePtr->width, + menuPtr->entries[i]->height); + } + mtdPtr->virtualMenuBottom = mtdPtr->virtualMenuTop + + menuPtr->totalHeight; + if (!EmptyRgn(utilRgn)) { + SetClip(utilRgn); + SetEmptyRgn(utilRgn); + } + MDEFScrollFlag = 1; +} + +/* + *---------------------------------------------------------------------- + * + * HandleMenuFindItemsMsg -- + * + * It handles the MenuDefProc's FindItems message. We have to + * respond by filling in the itemSelected, itemUnderMouse and + * itemRect fields. This is also the time to scroll the menu if + * it is too long to fit on the screen. + * + * Results: + * The Menu system is informed of the selected item & the item + * under the mouse. + * + * Side effects: + * The menu might get scrolled. + * + *---------------------------------------------------------------------- + */ +void +HandleMenuFindItemsMsg (MenuRef menu, + Rect *menuRectPtr, + Point hitPt, + SInt16 *whichItem, + TkMenu *menuPtr) +{ + TkMenuEntry *parentEntryPtr; + Tk_Font tkfont; + Tk_FontMetrics fontMetrics, entryMetrics; + Tk_FontMetrics *fmPtr; + TkMenuEntry *mePtr; + int i; + int newItem = -1; + GDHandle device; + Rect itemRect; + short windowPart; + WindowRef whichWindow; + RGBColor bgColor; + RGBColor fgColor; + RGBColor origFgColor; + PenState origPenState; + Rect dragRect; + Rect scratchRect = {-32768, -32768, 32767, 32767}; + RgnHandle oldClipRgn; + TkMenuReferences *menuRefPtr; + Rect menuClipRect; + + int hasTopScroll, hasBottomScroll; + MenuTrackingData * mtdPtr = (MenuTrackingData *)whichItem; + int itemUnderMouse = -1; + enum { + DONT_SCROLL, DOWN_SCROLL, UP_SCROLL + } scrollDirection; + Rect updateRect; + short scrollAmt = 0; + RGBColor origForeColor, origBackColor; + + /* + * Find out which item was hit. If it is the same as the old item, + * we don't need to do anything. + */ + + if (PtInRect(hitPt, menuRectPtr)) { + for (i = 0; i < menuPtr->numEntries; i++) { + mePtr = menuPtr->entries[i]; + itemRect.left = menuRectPtr->left + mePtr->x; + itemRect.top = mtdPtr->virtualMenuTop + mePtr->y; + if (mePtr->entryFlags & ENTRY_LAST_COLUMN) { + itemRect.right = itemRect.left + menuPtr->totalWidth + - mePtr->x; + } else { + itemRect.right = itemRect.left + mePtr->width; + } + itemRect.bottom = itemRect.top + + mePtr->height; + if (PtInRect(hitPt, &itemRect)) { + if ((mePtr->type == SEPARATOR_ENTRY) + || (mePtr->state == ENTRY_DISABLED)) { + newItem = -1; + itemUnderMouse = i; + } else { + TkMenuEntry *cascadeEntryPtr; + int parentDisabled = 0; + + for (cascadeEntryPtr + = menuPtr->menuRefPtr->parentEntryPtr; + cascadeEntryPtr != NULL; + cascadeEntryPtr + = cascadeEntryPtr->nextCascadePtr) { + char *name; + + name = Tcl_GetStringFromObj( + cascadeEntryPtr->namePtr, NULL); + if (strcmp(name, Tk_PathName(menuPtr->tkwin)) + == 0) { + if (cascadeEntryPtr->state == ENTRY_DISABLED) { + parentDisabled = 1; + } + break; + } + } + + if (parentDisabled) { + newItem = -1; + itemUnderMouse = i; + } else { + newItem = i; + itemUnderMouse = i; + } + } + break; + } + } + } else { + } + + /* + * Now we need to take care of scrolling the menu. + */ + + hasTopScroll = mtdPtr->virtualMenuTop < menuRectPtr->top; + hasBottomScroll = mtdPtr->virtualMenuBottom > menuRectPtr->bottom; + scrollDirection = DONT_SCROLL; + if (hasTopScroll && (hitPt.v < menuRectPtr->top + SICN_HEIGHT)) { + newItem = -1; + scrollDirection = DOWN_SCROLL; + } else if (hasBottomScroll && (hitPt.v > (menuRectPtr->bottom - SICN_HEIGHT))) { + newItem = -1; + scrollDirection = UP_SCROLL; + } + + menuClipRect = *menuRectPtr; + if (hasTopScroll) { + menuClipRect.top += SICN_HEIGHT; + } + if (hasBottomScroll) { + menuClipRect.bottom -= SICN_HEIGHT; + } + if (MDEFScrollFlag) { + scrollDirection = DONT_SCROLL; + MDEFScrollFlag = 0; + } + GetClip(utilRgn); + ClipRect(&menuClipRect); + + mtdPtr->itemSelected = newItem + 1; + mtdPtr->itemUnderMouse = itemUnderMouse + 1; + mtdPtr->itemRect = itemRect; + + GetGWorld(&macMDEFDrawable.grafPtr, &device); + GetForeColor(&origForeColor); + GetBackColor(&origBackColor); + + if (scrollDirection == UP_SCROLL) { + scrollAmt = menuClipRect.bottom - hitPt.v; + if (scrollAmt < menuRectPtr->bottom + - mtdPtr->virtualMenuBottom) { + scrollAmt = menuRectPtr->bottom - mtdPtr->virtualMenuBottom; + } + if (!hasTopScroll && ((mtdPtr->virtualMenuTop + scrollAmt) + < menuRectPtr->top)) { + SetRect(&updateRect, menuRectPtr->left, + mtdPtr->virtualMenuTop, menuRectPtr->right, + mtdPtr->virtualMenuTop + SICN_HEIGHT); + EraseRect(&updateRect); + DrawSICN(SICN_RESOURCE_NUMBER, UP_ARROW, + (Drawable) &macMDEFDrawable, + menuPtr->textGC, menuRectPtr->left + + menuPtr->entries[1]->indicatorSpace, + menuRectPtr->top); + menuClipRect.top += SICN_HEIGHT; + } + } else if (scrollDirection == DOWN_SCROLL) { + + scrollAmt = menuClipRect.top - hitPt.v; + if (scrollAmt > menuRectPtr->top - mtdPtr->virtualMenuTop) { + scrollAmt = menuRectPtr->top - mtdPtr->virtualMenuTop; + } + + if (!hasBottomScroll && ((mtdPtr->virtualMenuBottom + scrollAmt) + > menuRectPtr->bottom)) { + SetRect(&updateRect, menuRectPtr->left, + mtdPtr->virtualMenuBottom - SICN_HEIGHT, + menuRectPtr->right, mtdPtr->virtualMenuBottom); + EraseRect(&updateRect); + DrawSICN(SICN_RESOURCE_NUMBER, DOWN_ARROW, + (Drawable) &macMDEFDrawable, + menuPtr->textGC, menuRectPtr->left + + menuPtr->entries[1]->indicatorSpace, + menuRectPtr->bottom - SICN_HEIGHT); + menuClipRect.bottom -= SICN_HEIGHT; + } + } + + if (scrollDirection != DONT_SCROLL) { + Tk_Font menuFont; + RgnHandle updateRgn = NewRgn(); + + ScrollMenuImage(menu, menuRectPtr, 0, scrollAmt, NULL); + mtdPtr->virtualMenuTop += scrollAmt; + mtdPtr->virtualMenuBottom += scrollAmt; +#if 0 + GetRegionBounds(updateRgn,&updateRect); + DisposeRgn(updateRgn); + if (mtdPtr->virtualMenuTop == menuRectPtr->top) { + updateRect.top -= SICN_HEIGHT; + } + if (mtdPtr->virtualMenuBottom == menuRectPtr->bottom) { + updateRect.bottom += SICN_HEIGHT; + } + ClipRect(&updateRect); + EraseRect(&updateRect); + menuFont = Tk_GetFontFromObj(menuPtr->tkwin, menuPtr->fontPtr); + Tk_GetFontMetrics(menuFont, &fontMetrics); + for (i = 0; i < menuPtr->numEntries; i++) { + mePtr = menuPtr->entries[i]; + if (mtdPtr->virtualMenuTop + mePtr->y + mePtr->height + < updateRect.top) { + continue; + } else if (mtdPtr->virtualMenuTop + mePtr->y + > updateRect.bottom) { + continue; + } + if (mePtr->fontPtr == NULL) { + fmPtr = &fontMetrics; + tkfont = menuFont; + } else { + tkfont = Tk_GetFontFromObj(menuPtr->tkwin, + mePtr->fontPtr); + Tk_GetFontMetrics(tkfont, &entryMetrics); + fmPtr = &entryMetrics; + } + AppearanceEntryDrawWrapper(mePtr, menuRectPtr, mtdPtr, + (Drawable) &macMDEFDrawable, fmPtr, tkfont, + menuRectPtr->left + mePtr->x, + mtdPtr->virtualMenuTop + mePtr->y, + (mePtr->entryFlags & ENTRY_LAST_COLUMN) ? + menuPtr->totalWidth - mePtr->x : mePtr->width, + menuPtr->entries[i]->height); + } +#endif + } + + SetClip(utilRgn); + SetEmptyRgn(utilRgn); + RGBForeColor(&origForeColor); + RGBBackColor(&origBackColor); + + /* + * If the menu is a tearoff, and the mouse is outside the menu, + * we need to draw the drag rectangle. + * + * In order for tearoffs to work properly, we need to set + * the active member of the containing menubar. + */ + + menuRefPtr = TkFindMenuReferences(menuPtr->interp, + Tk_PathName(menuPtr->tkwin)); + + if ((menuRefPtr != NULL) && (menuRefPtr->parentEntryPtr != NULL)) { + char *name; + for (parentEntryPtr = menuRefPtr->parentEntryPtr; + parentEntryPtr != NULL + ; parentEntryPtr = parentEntryPtr->nextCascadePtr) { + name = Tcl_GetStringFromObj(parentEntryPtr->namePtr, + NULL); + if (strcmp(name, Tk_PathName(menuPtr->tkwin)) != 0) { + break; + } + } + if (parentEntryPtr != NULL) { + TkActivateMenuEntry(parentEntryPtr->menuPtr, + parentEntryPtr->index); + } + } + + if (menuPtr->tearoff) { + scratchRect = *menuRectPtr; + if (tearoffStruct.menuPtr == NULL) { + scratchRect.top -= 10; + scratchRect.bottom += 10; + scratchRect.left -= 10; + scratchRect.right += 10; + } + + windowPart = FindWindow(hitPt, &whichWindow); + if ((windowPart != inMenuBar) && (newItem == -1) + && (hitPt.v != 0) && (hitPt.h != 0) + && (!PtInRect(hitPt, &scratchRect)) + && (!PtInRect(hitPt, &tearoffStruct.excludeRect))) { + unsigned long dummy; + oldClipRgn = NewRgn(); + GetClip(oldClipRgn); + GetForeColor(&origFgColor); + GetPenState(&origPenState); + GetForeColor(&fgColor); + GetBackColor(&bgColor); + GetGray(device, &bgColor, &fgColor); + RGBForeColor(&fgColor); + SetRect(&scratchRect, -32768, -32768, 32767, 32767); + ClipRect(&scratchRect); + + dragRect = *menuRectPtr; + tearoffStruct.menuPtr = menuPtr; + + PenMode(srcXor); + dragRect = *menuRectPtr; + OffsetRect(&dragRect, -dragRect.left, -dragRect.top); + OffsetRect(&dragRect, tearoffStruct.point.h, + tearoffStruct.point.v); + if ((dragRect.top != 0) && (dragRect.left != 0)) { + FrameRect(&dragRect); + Delay(1, &dummy); + FrameRect(&dragRect); + } + tearoffStruct.point = hitPt; + + SetClip(oldClipRgn); + DisposeRgn(oldClipRgn); + RGBForeColor(&origFgColor); + SetPenState(&origPenState); + } else { + tearoffStruct.menuPtr = NULL; + tearoffStruct.point.h = tearoffStruct.point.v = 0; + } + } else { + tearoffStruct.menuPtr = NULL; + tearoffStruct.point.h = tearoffStruct.point.v = 0; + } +} + +/* + *---------------------------------------------------------------------- + * + * HandleMenuPopUpMsg -- + * + * It handles the MenuDefProc's PopUp message. The menu is + * posted with the selected item at the point given in hitPt. + * + * Results: + * A menu is posted. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +void +HandleMenuPopUpMsg (MenuRef menu, + Rect *menuRectPtr, + Point hitPt, + SInt16 *whichItem, + TkMenu *menuPtr) +{ + int maxMenuHeight; + int oldItem; + Rect portRect; + BitMap screenBits; + + /* + * Note that for some oddball reason, h and v are reversed in the + * point given to us by the MDEF. + */ + GetQDGlobalsScreenBits(&screenBits); + + oldItem = *whichItem; + if (oldItem >= menuPtr->numEntries) { + oldItem = -1; + } + portRect.top = 0; + portRect.bottom = 1280; + maxMenuHeight = screenBits.bounds.bottom + - screenBits.bounds.top + - GetMBarHeight() - SCREEN_MARGIN; + if (menuPtr->totalHeight > maxMenuHeight) { + menuRectPtr->top = GetMBarHeight(); + } else { + int delta; + menuRectPtr->top = hitPt.h; + if (oldItem >= 0) { + menuRectPtr->top -= menuPtr->entries[oldItem]->y; + } + + if (menuRectPtr->top < GetMBarHeight()) { + /* Displace downward if the menu would stick off the + * top of the screen. + */ + + menuRectPtr->top = GetMBarHeight() + SCREEN_MARGIN; + } else { + /* + * Or upward if the menu sticks off the + * bottom end... + */ + + delta = menuRectPtr->top + menuPtr->totalHeight + - maxMenuHeight; + if (delta > 0) { + menuRectPtr->top -= delta; + } + } + } + menuRectPtr->left = hitPt.v; + menuRectPtr->right = menuRectPtr->left + menuPtr->totalWidth; + menuRectPtr->bottom = menuRectPtr->top + + ((maxMenuHeight < menuPtr->totalHeight) + ? maxMenuHeight : menuPtr->totalHeight); + if (menuRectPtr->top == GetMBarHeight()) { + *whichItem = hitPt.h; + } else { + *whichItem = menuRectPtr->top; + } +} + +/* + *---------------------------------------------------------------------- + * + * HandleMenuCalcItemMsg -- + * + * It handles the MenuDefProc's CalcItem message. It is supposed + * to calculate the Rect of the menu entry in whichItem in the + * menu, and put that in menuRectPtr. I assume this works, but I + * have never seen the MenuManager send this message. + * + * Results: + * The Menu Manager is informed of the bounding rect of a + * menu rect. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +void +HandleMenuCalcItemMsg(MenuRef menu, + Rect *menuRectPtr, + Point hitPt, + SInt16 *whichItem, + TkMenu *menuPtr) +{ + TkMenuEntry *mePtr; + MenuTrackingData mtd, *mtdPtr = &mtd; + int err, virtualTop; + + err = GetMenuTrackingData(menu, mtdPtr); + if (err == noErr) { + virtualTop = mtdPtr->virtualMenuTop; + } else { + virtualTop = 0; + } + + mePtr = menuPtr->entries[*whichItem]; + menuRectPtr->left = mePtr->x; + menuRectPtr->top = mePtr->y - virtualTop; + if (mePtr->entryFlags & ENTRY_LAST_COLUMN) { + menuRectPtr->right = menuPtr->totalWidth; + } else { + menuRectPtr->right = mePtr->x + mePtr->width; + } + menuRectPtr->bottom = menuRectPtr->top + + mePtr->height; +} diff --git a/macosx/tkMacOSXMenu.r b/macosx/tkMacOSXMenu.r new file mode 100644 index 0000000..3a71886 --- /dev/null +++ b/macosx/tkMacOSXMenu.r @@ -0,0 +1,47 @@ +/* + * tkMacOSXMenu.r -- + * + * Resources needed by menus. + * + * This file also contains the icons 'SICN' used by the menu code + * in menu items. + * + * 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: tkMacOSXMenu.r,v 1.2 2002/08/31 06:12:30 das Exp $ + */ + +#include <Carbon.r> + +/* + * Icons used in menu items. + */ + +resource 'SICN' (128, preload, locked) { + { /* array: 7 elements */ + /* [1] */ + $"0000 0000 8000 C000 E000 F000 F800 FC00" + $"F800 F000 E000 C000 80", + /* [2] */ + $"0000 0000 0000 0800 1400 2200 4100 8080" + $"E380 2200 2200 2200 3E", + /* [3] */ + $"0000 0000 0000 0000 0000 F8F0 C4F0 F270" + $"0900 0480 0270 0130 00F0", + /* [4] */ + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0000 E4E0 CE60 1B00 3180", + /* [5] */ + $"0000 0000 0000 0000 6300 9480 9480 7F00" + $"1400 7F00 9480 9480 63", + /* [6] */ + $"0000 0000 0000 0000 0000 3FF8 1FF0 0FE0" + $"07C0 0380 01", + /* [7] */ + $"0000 0000 0000 0000 0000 0100 0380 07C0" + $"0FE0 1FF0 3FF8" + } +}; diff --git a/macosx/tkMacOSXMenubutton.c b/macosx/tkMacOSXMenubutton.c new file mode 100644 index 0000000..52b239c --- /dev/null +++ b/macosx/tkMacOSXMenubutton.c @@ -0,0 +1,861 @@ +/* + * tkMacOSXMenubutton.c -- + * + * This file implements the Macintosh specific portion of the + * menubutton widget. + * + * Copyright (c) 1996 by Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkMacOSXMenubutton.c,v 1.2 2002/08/31 06:12:30 das Exp $ + */ + +#include <Carbon/Carbon.h> +#include "tkMenu.h" +#include "tkMenubutton.h" +#include "tkMacOSXInt.h" +#include "tkMacOSXDebug.h" + +#define kShadowOffset (3) /* amount to offset shadow from frame */ +#define kTriangleWidth (11) /* width of the triangle */ +#define kTriangleHeight (6) /* height of the triangle */ +#define kTriangleMargin (5) /* margin around triangle */ + +#define TK_POPUP_OFFSET 32 /* size of popup marker */ + +int TkMacOSXGetNewMenuID _ANSI_ARGS_((Tcl_Interp *interp, TkMenu *menuInstPtr, int cascade, short *menuIDPtr)); +void TkMacOSXFreeMenuID _ANSI_ARGS_((short menuID)); + +typedef struct { + SInt16 initialValue; + SInt16 minValue; + SInt16 maxValue; + SInt16 procID; + int isBevel; +} MenuButtonControlParams; + +typedef struct { + int len; + Str255 title; + ControlFontStyleRec style; +} ControlTitleParams; + +/* + * Declaration of Mac specific button structure. + */ + +typedef struct MacMenuButton { + TkMenuButton info; /* Generic button info. */ + WindowRef windowRef; + ControlRef userPane; + ControlRef control; + MenuRef menuRef; + RGBColor userPaneBackground; + MenuButtonControlParams params; + ControlTitleParams titleParams; + ControlButtonContentInfo bevelButtonContent; + OpenCPicParams picParams; + int flags; +} MacMenuButton; + +/* + * Forward declarations for procedures defined later in this file: + */ + +static OSErr SetUserPaneDrawProc(ControlRef control, + ControlUserPaneDrawProcPtr upp); +static OSErr SetUserPaneSetUpSpecialBackgroundProc(ControlRef control, + ControlUserPaneBackgroundProcPtr upp); +static void UserPaneDraw(ControlRef control, ControlPartCode cpc); +static void UserPaneBackgroundProc(ControlHandle, + ControlBackgroundPtr info); +static int MenuButtonInitControl ( MacMenuButton *mbPtr, Rect *paneRect, Rect *cntrRect ); + +static int UpdateControlColors _ANSI_ARGS_((MacMenuButton *mbPtr )); +static void ComputeMenuButtonControlParams _ANSI_ARGS_((TkMenuButton * mbPtr, MenuButtonControlParams * paramsPtr)); +static void ComputeControlTitleParams _ANSI_ARGS_((TkMenuButton * mbPtr, ControlTitleParams * paramsPtr)); +static void CompareControlTitleParams( + ControlTitleParams * p1Ptr, + ControlTitleParams * p2Ptr, + int * titleChanged, + int * styleChanged +); + +extern int TkFontGetFirstTextLayout(Tk_TextLayout layout, Tk_Font * font, char * dst); +extern void TkMacOSXInitControlFontStyle(Tk_Font tkfont,ControlFontStylePtr fsPtr); + +extern int tkPictureIsOpen; + +/* + * The structure below defines menubutton class behavior by means of + * procedures that can be invoked from generic window code. + */ + +Tk_ClassProcs tkpMenubuttonClass = { + sizeof(Tk_ClassProcs), /* size */ + TkMenuButtonWorldChanged, /* worldChangedProc */ +}; + +/* + *---------------------------------------------------------------------- + * + * TkpCreateMenuButton -- + * + * Allocate a new TkMenuButton structure. + * + * Results: + * Returns a newly allocated TkMenuButton structure. + * + * Side effects: + * Registers an event handler for the widget. + * + *---------------------------------------------------------------------- + */ + +TkMenuButton * +TkpCreateMenuButton( + Tk_Window tkwin) +{ + MacMenuButton *mbPtr = (MacMenuButton *) ckalloc(sizeof(MacMenuButton)); + mbPtr->userPaneBackground.red = 0; + mbPtr->userPaneBackground.green = 0; + mbPtr->userPaneBackground.blue = ~0; + mbPtr->flags = 0; + mbPtr->userPane = NULL; + mbPtr->control = NULL; + mbPtr->picParams.version = -2; + mbPtr->picParams.hRes = 0x00480000; + mbPtr->picParams.vRes = 0x00480000; + mbPtr->picParams.srcRect.top = 0; + mbPtr->picParams.srcRect.left = 0; + mbPtr->picParams.reserved1 = 0; + mbPtr->picParams.reserved2 = 0; + mbPtr->bevelButtonContent.contentType = kControlContentPictHandle; + mbPtr->menuRef = NULL; + + bzero(&mbPtr->params, sizeof(mbPtr->params)); + bzero(&mbPtr->titleParams,sizeof(mbPtr->titleParams)); + return (TkMenuButton *) mbPtr; +} + +/* + *---------------------------------------------------------------------- + * + * TkpDisplayMenuButton -- + * + * This procedure is invoked to display a menubutton widget. + * + * Results: + * None. + * + * Side effects: + * Commands are output to X to display the menubutton in its + * current mode. + * + *---------------------------------------------------------------------- + */ + +void +TkpDisplayMenuButton( + ClientData clientData) /* Information about widget. */ +{ + TkMenuButton *butPtr = (TkMenuButton *) clientData; + Tk_Window tkwin = butPtr->tkwin; + TkWindow * winPtr; + Pixmap pixmap; + MacMenuButton * mbPtr = (MacMenuButton *) butPtr; + GWorldPtr dstPort; + CGrafPtr saveWorld; + GDHandle saveDevice; + int hasImageOrBitmap = 0; + int width, height; + int err; + ControlButtonGraphicAlignment theAlignment; + + Rect paneRect, cntrRect; + + butPtr->flags &= ~REDRAW_PENDING; + if ((butPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { + return; + } + pixmap = ( Pixmap )Tk_WindowId(tkwin); + GetGWorld(&saveWorld, &saveDevice); + dstPort = TkMacOSXGetDrawablePort(Tk_WindowId(tkwin)); + SetGWorld(dstPort, NULL); + TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin)); + + winPtr=(TkWindow *)butPtr->tkwin; + paneRect.left=winPtr->privatePtr->xOff; + paneRect.top=winPtr->privatePtr->yOff; + paneRect.right=paneRect.left+Tk_Width(butPtr->tkwin)-1; + paneRect.bottom=paneRect.top+Tk_Height(butPtr->tkwin)-1; + + cntrRect=paneRect; + + cntrRect.left+=butPtr->inset; + cntrRect.top+=butPtr->inset; + cntrRect.right-=butPtr->inset; + cntrRect.bottom-=butPtr->inset; + + if (mbPtr->userPane) { + MenuButtonControlParams params; + bzero(¶ms, sizeof(params)); + ComputeMenuButtonControlParams(butPtr, ¶ms ); + if (bcmp(¶ms,&mbPtr->params,sizeof(params))) { + if (mbPtr->userPane) { + DisposeControl(mbPtr->userPane); + mbPtr->userPane = NULL; + mbPtr->control = NULL; + } + } + } + if (!mbPtr->userPane) { + if (MenuButtonInitControl(mbPtr,&paneRect,&cntrRect ) ) { + fprintf(stderr,"Init Control failed\n" ); + return; + } + } + SetControlBounds(mbPtr->userPane,&paneRect); + SetControlBounds(mbPtr->control,&cntrRect); + + /* + * We need to cache the title and its style + */ + if (!(mbPtr->flags&2)) { + ControlTitleParams titleParams; + int titleChanged; + int styleChanged; + ComputeControlTitleParams(butPtr,&titleParams); + CompareControlTitleParams(&titleParams,&mbPtr->titleParams, + &titleChanged,&styleChanged); + if (titleChanged) { + CFStringRef cf; + cf = CFStringCreateWithCString(NULL, + titleParams.title, kCFStringEncodingUTF8); + if (hasImageOrBitmap) { + SetControlTitleWithCFString(mbPtr->control, cf); + } else { + SetMenuItemTextWithCFString(mbPtr->menuRef, 1, cf); + } + CFRelease(cf); + bcopy(titleParams.title,mbPtr->titleParams.title,titleParams.len+1); + mbPtr->titleParams.len = titleParams.len; + } + if ((titleChanged||styleChanged) && titleParams .len) { + if (hasImageOrBitmap) { + if ((err=SetControlFontStyle(mbPtr->control,&titleParams.style))!=noErr) { + fprintf(stderr,"SetControlFontStyle failed %d\n", err); + return; + } + } + bcopy(&titleParams.style,&mbPtr->titleParams.style,sizeof(titleParams.style)); + } + } + if (butPtr->image != None) { + Tk_SizeOfImage(butPtr->image, &width, &height); + hasImageOrBitmap = 1; + } else if (butPtr->bitmap != None) { + Tk_SizeOfBitmap(butPtr->display, butPtr->bitmap, &width, &height); + hasImageOrBitmap = 1; + } + if (hasImageOrBitmap) { + mbPtr->picParams.srcRect.right = width; + mbPtr->picParams.srcRect.bottom = height; + /* Set the flag to circumvent clipping and bounds problems with OS 10.0.4 */ + tkPictureIsOpen = 1; + if (!(mbPtr->bevelButtonContent.u.picture = OpenCPicture(&mbPtr->picParams)) ) { + fprintf(stderr,"OpenCPicture failed\n"); + } + /* + * TO DO - There is one case where XCopyPlane calls CopyDeepMask, + * which does not get recorded in the picture. So the bitmap code + * will fail in that case. + */ + if (butPtr->image != NULL) { + Tk_RedrawImage(butPtr->image, 0, 0, width, + height, pixmap, 0, 0); + } else { + XCopyPlane(butPtr->display, butPtr->bitmap, pixmap, NULL, 0, 0, + (unsigned int) width, (unsigned int) height, 0, 0, 1); + } + ClosePicture(); + + tkPictureIsOpen = 0; + if ( (err=SetControlData(mbPtr->control, kControlButtonPart, + kControlBevelButtonContentTag, + sizeof(ControlButtonContentInfo), + (char *) &mbPtr->bevelButtonContent)) != noErr ) { + fprintf(stderr,"SetControlData BevelButtonContent failed, %d\n", err ); + } + switch (butPtr->anchor) { + case TK_ANCHOR_N: + theAlignment = kControlBevelButtonAlignTop; + break; + case TK_ANCHOR_NE: + theAlignment = kControlBevelButtonAlignTopRight; + break; + case TK_ANCHOR_E: + theAlignment = kControlBevelButtonAlignRight; + break; + case TK_ANCHOR_SE: + theAlignment = kControlBevelButtonAlignBottomRight; + break; + case TK_ANCHOR_S: + theAlignment = kControlBevelButtonAlignBottom; + break; + case TK_ANCHOR_SW: + theAlignment = kControlBevelButtonAlignBottomLeft; + break; + case TK_ANCHOR_W: + theAlignment = kControlBevelButtonAlignLeft; + break; + case TK_ANCHOR_NW: + theAlignment = kControlBevelButtonAlignTopLeft; + break; + case TK_ANCHOR_CENTER: + theAlignment = kControlBevelButtonAlignCenter; + break; + } + + if ((err=SetControlData(mbPtr->control, kControlButtonPart, + kControlBevelButtonGraphicAlignTag, + sizeof(ControlButtonGraphicAlignment), + (char *) &theAlignment)) != noErr ) { + fprintf(stderr,"SetControlData BevelButtonGraphicAlign failed, %d\n", err ); + } + } + if (butPtr->flags & GOT_FOCUS) { + HiliteControl(mbPtr->control,kControlButtonPart); + } else { + HiliteControl(mbPtr->control,kControlNoPart); + } + UpdateControlColors(mbPtr); + if (mbPtr->flags&2) { + ShowControl(mbPtr->control); + ShowControl(mbPtr->userPane); + mbPtr->flags ^= 2; + } else { + Draw1Control(mbPtr->userPane); + SetControlVisibility(mbPtr->control, true, true); + } + if (hasImageOrBitmap) { + KillPicture(mbPtr->bevelButtonContent.u.picture); + } + SetGWorld(saveWorld, saveDevice); +} + +/* + *---------------------------------------------------------------------- + * + * TkpDestroyMenuButton -- + * + * Free data structures associated with the menubutton control. + * + * Results: + * None. + * + * Side effects: + * Restores the default control state. + * + *---------------------------------------------------------------------- + */ + +void +TkpDestroyMenuButton( + TkMenuButton *mbPtr) +{ + MacMenuButton * macMbPtr = (MacMenuButton *)mbPtr; + if (macMbPtr->userPane) { + DisposeControl(macMbPtr->userPane); + macMbPtr->userPane = NULL; + } + if (macMbPtr->menuRef) { + short menuID; + menuID = GetMenuID(macMbPtr->menuRef); + TkMacOSXFreeMenuID(menuID); + DisposeMenu(macMbPtr->menuRef); + macMbPtr->menuRef = NULL; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpComputeMenuButtonGeometry -- + * + * After changes in a menu button's text or bitmap, this procedure + * recomputes the menu button's geometry and passes this information + * along to the geometry manager for the window. + * + * Results: + * None. + * + * Side effects: + * The menu button's window may change size. + * + *---------------------------------------------------------------------- + */ + +void +TkpComputeMenuButtonGeometry(mbPtr) + register TkMenuButton *mbPtr; /* Widget record for menu button. */ +{ + int width, height, mm, pixels; + int hasImageOrBitmap = 0; + + mbPtr->inset = mbPtr->highlightWidth + mbPtr->borderWidth; + if (mbPtr->image != None) { + Tk_SizeOfImage(mbPtr->image, &width, &height); + if (mbPtr->width > 0) { + width = mbPtr->width; + } + if (mbPtr->height > 0) { + height = mbPtr->height; + } + hasImageOrBitmap = 1; + } else if (mbPtr->bitmap != None) { + Tk_SizeOfBitmap(mbPtr->display, mbPtr->bitmap, &width, &height); + if (mbPtr->width > 0) { + width = mbPtr->width; + } + if (mbPtr->height > 0) { + height = mbPtr->height; + } + hasImageOrBitmap = 1; + } else { + hasImageOrBitmap = 0; + Tk_FreeTextLayout(mbPtr->textLayout); + mbPtr->textLayout = Tk_ComputeTextLayout(mbPtr->tkfont, mbPtr->text, + -1, mbPtr->wrapLength, mbPtr->justify, 0, &mbPtr->textWidth, + &mbPtr->textHeight); + width = mbPtr->textWidth; + height = mbPtr->textHeight; + if (mbPtr->width > 0) { + width = mbPtr->width * Tk_TextWidth(mbPtr->tkfont, "0", 1); + } + if (mbPtr->height > 0) { + Tk_FontMetrics fm; + + Tk_GetFontMetrics(mbPtr->tkfont, &fm); + height = mbPtr->height * fm.linespace; + } + width += 2*mbPtr->padX; + height += 2*mbPtr->padY; + } + + if (mbPtr->indicatorOn) { + mm = WidthMMOfScreen(Tk_Screen(mbPtr->tkwin)); + pixels = WidthOfScreen(Tk_Screen(mbPtr->tkwin)); + mbPtr->indicatorHeight= kTriangleHeight; + mbPtr->indicatorWidth = kTriangleWidth + kTriangleMargin; + width += mbPtr->indicatorWidth; + } else { + mbPtr->indicatorHeight = 0; + mbPtr->indicatorWidth = 0; + } + if (!hasImageOrBitmap) { + width += TK_POPUP_OFFSET; + } + + Tk_GeometryRequest(mbPtr->tkwin, (int) (width + 2*mbPtr->inset), + (int) (height + 2*mbPtr->inset)); + Tk_SetInternalBorder(mbPtr->tkwin, mbPtr->inset); +} + +/* + *---------------------------------------------------------------------- + * + * ComputeMenuButtonControlParams -- + * + * This procedure computes the various parameters used + * when creating a Carbon control (NewControl) + * These are determined by the various tk menu button parameters + * + * Results: + * None. + * + * Side effects: + * Sets the control initialisation parameters + * + *---------------------------------------------------------------------- + */ + +static void +ComputeMenuButtonControlParams(TkMenuButton * mbPtr, + MenuButtonControlParams * paramsPtr ) +{ + int fakeMenuID = 256; + + /* + * Determine ProcID based on button type and dimensions + * + * We need to set minValue to some non-zero value, + * Otherwise, the markers do not show up + */ + + paramsPtr->minValue = kControlBehaviorMultiValueMenu; + paramsPtr->maxValue = 0; + if (mbPtr->image || mbPtr->bitmap) { + paramsPtr->isBevel = 1; + if (mbPtr->borderWidth <= 2) { + paramsPtr->procID = kControlBevelButtonSmallBevelProc; + } else if (mbPtr->borderWidth == 3) { + paramsPtr->procID = kControlBevelButtonNormalBevelProc; + } else { + paramsPtr->procID = kControlBevelButtonLargeBevelProc; + } + if (mbPtr->indicatorOn) { + paramsPtr->initialValue = fakeMenuID; + } else { + paramsPtr->initialValue = 0; + } + } else { + paramsPtr->isBevel = 0; + paramsPtr->procID = kControlPopupButtonProc + + kControlPopupVariableWidthVariant; + paramsPtr->minValue = -12345; + paramsPtr->maxValue = -1; + paramsPtr->initialValue = 0; + } +} + +/* + *---------------------------------------------------------------------- + * + * returns 0 if same, 1 otherwise + *---------------------------------------------------------------------- + */ +static void +CompareControlTitleParams( + ControlTitleParams * p1Ptr, + ControlTitleParams * p2Ptr, + int * titleChanged, + int * styleChanged +) +{ + if (p1Ptr->len != p2Ptr->len) { + *titleChanged = 1; + } else { + if (bcmp(p1Ptr->title,p2Ptr->title,p1Ptr->len)) { + *titleChanged = 1; + } else { + *titleChanged = 0; + } + } + if (p1Ptr->len && p2Ptr->len) { + *styleChanged = bcmp(&p1Ptr->style, &p2Ptr->style, sizeof(p2Ptr->style)); + } else { + *styleChanged = p1Ptr->len||p2Ptr->len; + } +} + +static void +ComputeControlTitleParams(TkMenuButton * butPtr, ControlTitleParams * paramsPtr ) +{ + Tk_Font font; + paramsPtr->len =TkFontGetFirstTextLayout(butPtr->textLayout,&font, paramsPtr->title); + paramsPtr->title [paramsPtr->len] = 0; + if (paramsPtr->len) { + TkMacOSXInitControlFontStyle(font,¶msPtr->style); + } +} + + +/* + *---------------------------------------------------------------------- + * + * MenuButtonInitControl -- + * + * This procedure initialises a Carbon control + * + * Results: + * 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 + * + *---------------------------------------------------------------------- + */ +int +MenuButtonInitControl ( + MacMenuButton *mbPtr, /* Mac button. */ + Rect *paneRect, + Rect *cntrRect +) +{ + OSErr status; + TkMenuButton * butPtr = ( TkMenuButton * )mbPtr; + ControlRef rootControl; + SInt16 procID; + Boolean initiallyVisible; + SInt16 initialValue; + SInt16 minValue; + SInt16 maxValue; + SInt32 controlReference; + int err; + short menuID; + int length; + Str255 itemText; + + rootControl=TkMacOSXGetRootControl(Tk_WindowId(butPtr->tkwin)); + mbPtr->windowRef=GetWindowFromPort(TkMacOSXGetDrawablePort(Tk_WindowId(butPtr->tkwin))); + /* + * Set up the user pane + */ + initiallyVisible = false; + 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 ); + if (!mbPtr->userPane) { + fprintf(stderr,"Failed to create user pane control\n"); + return 1; + } + if ((status=EmbedControl(mbPtr->userPane,rootControl))!=noErr) { + fprintf(stderr,"Failed to embed user pane control %d\n", status); + return 1; + } + SetUserPaneSetUpSpecialBackgroundProc(mbPtr->userPane, + UserPaneBackgroundProc); + SetUserPaneDrawProc(mbPtr->userPane,UserPaneDraw); + initiallyVisible = false; + ComputeMenuButtonControlParams(butPtr,&mbPtr->params); + /* Do this only if we are using bevel buttons */ + ComputeControlTitleParams(butPtr,&mbPtr->titleParams); + mbPtr->control = NewControl(mbPtr->windowRef, + cntrRect, "\p", //mbPtr->titleParams.title, + initiallyVisible, + mbPtr->params.initialValue, + mbPtr->params.minValue, + mbPtr->params.maxValue, + mbPtr->params.procID, + controlReference ); + if (!mbPtr->control) { + fprintf(stderr,"failed to create control of type %d : line %d\n",mbPtr->params.procID, __LINE__); + return 1; + } + if ((err=EmbedControl(mbPtr->control,mbPtr->userPane)) != noErr ) { + fprintf(stderr,"failed to embed control of type %d,%d\n",procID, err); + return 1; + } + if (mbPtr->params.isBevel) { + CFStringRef cf; + cf = CFStringCreateWithCString(NULL, + mbPtr->titleParams.title, kCFStringEncodingUTF8); + SetControlTitleWithCFString(mbPtr->control, cf); + CFRelease(cf); + if (mbPtr->titleParams.len) { + if ((err=SetControlFontStyle(mbPtr->control,&mbPtr->titleParams.style))!=noErr) { + fprintf(stderr,"SetControlFontStyle failed %d\n", err); + return 1; + } + } + } else { + CFStringRef cf; + err = TkMacOSXGetNewMenuID(mbPtr->info.interp, (TkMenu *)mbPtr, 0, &menuID); + if (err != TCL_OK) { + return err; + } + length = strlen(Tk_PathName(mbPtr->info.tkwin)); + memmove(&itemText[1], Tk_PathName(mbPtr->info.tkwin), + (length > 230) ? 230 : length); + itemText[0] = (length > 230) ? 230 : length; + if (!(mbPtr->menuRef = NewMenu(menuID,itemText))) { + return 1; + } + cf = CFStringCreateWithCString(NULL, + mbPtr->titleParams.title, kCFStringEncodingUTF8); + AppendMenuItemText(mbPtr->menuRef, "\px"); + if (cf != NULL) { + SetMenuItemTextWithCFString(mbPtr->menuRef, 1, cf); + CFRelease(cf); + } + err = SetControlData(mbPtr->control, + kControlNoPart, + kControlPopupButtonMenuRefTag, + sizeof(mbPtr->menuRef), &mbPtr->menuRef); + SetControlMinimum(mbPtr->control, 1); + SetControlMaximum(mbPtr->control, 1); + SetControlValue(mbPtr->control, 1); + } + mbPtr->flags |= 2; + return 0; +} + +/* + *-------------------------------------------------------------- + * + * SetUserPane + * + * Utility function to add a UserPaneDrawProc + * to a userPane control. From MoreControls code + * from Apple DTS. + * + * Results: + * MacOS system error. + * + * Side effects: + * The user pane gets a new UserPaneDrawProc. + * + *-------------------------------------------------------------- + */ +OSErr SetUserPaneDrawProc ( + ControlRef control, + ControlUserPaneDrawProcPtr upp) +{ + ControlUserPaneDrawUPP myControlUserPaneDrawUPP; + myControlUserPaneDrawUPP = NewControlUserPaneDrawUPP(upp); + return SetControlData (control, + kControlNoPart, kControlUserPaneDrawProcTag, + sizeof(myControlUserPaneDrawUPP), + (Ptr) &myControlUserPaneDrawUPP); +} + +/* + *-------------------------------------------------------------- + * + * SetUserPaneSetUpSpecialBackgroundProc -- + * + * Utility function to add a UserPaneBackgroundProc + * to a userPane control + * + * Results: + * MacOS system error. + * + * Side effects: + * The user pane gets a new UserPaneBackgroundProc. + * + *-------------------------------------------------------------- + */ +OSErr +SetUserPaneSetUpSpecialBackgroundProc( + ControlRef control, + ControlUserPaneBackgroundProcPtr upp) +{ + ControlUserPaneBackgroundUPP myControlUserPaneBackgroundUPP; + myControlUserPaneBackgroundUPP = NewControlUserPaneBackgroundUPP(upp); + return SetControlData (control, kControlNoPart, + kControlUserPaneBackgroundProcTag, + sizeof(myControlUserPaneBackgroundUPP), + (Ptr) &myControlUserPaneBackgroundUPP); +} + +/* + *-------------------------------------------------------------- + * + * UserPaneDraw -- + * + * This function draws the background of the user pane that will + * lie under checkboxes and radiobuttons. + * + * Results: + * None. + * + * Side effects: + * The user pane gets updated to the current color. + * + *-------------------------------------------------------------- + */ +void +UserPaneDraw( + ControlRef control, + ControlPartCode cpc) +{ + Rect contrlRect; + MacMenuButton * mbPtr; + mbPtr = ( MacMenuButton *)GetControlReference(control); + GetControlBounds(control,&contrlRect); + RGBBackColor (&mbPtr->userPaneBackground); + EraseRect (&contrlRect); +} + +/* + *-------------------------------------------------------------- + * + * UserPaneBackgroundProc -- + * + * This function sets up the background of the user pane that will + * lie under checkboxes and radiobuttons. + * + * Results: + * None. + * + * Side effects: + * The user pane background gets set to the current color. + * + *-------------------------------------------------------------- + */ + +void +UserPaneBackgroundProc( + ControlHandle control, + ControlBackgroundPtr info) +{ + MacMenuButton * mbPtr; + mbPtr = (MacMenuButton *)GetControlReference(control); + if (info->colorDevice) { + RGBBackColor (&mbPtr->userPaneBackground); + } +} + +/* + *-------------------------------------------------------------- + * + * 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. + * + * Under Appearance, we just set the pointer that will be + * used by the UserPaneDrawProc. + * + * Results: + * None. + * + * Side effects: + * The Macintosh control may get a custom palette installed. + * + *-------------------------------------------------------------- + */ + +static int +UpdateControlColors(MacMenuButton * mbPtr) +{ + XColor *xcolor; + TkMenuButton * butPtr = ( TkMenuButton * )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. + * 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. + */ + + xcolor = Tk_3DBorderColor(butPtr->normalBorder); + TkSetMacColor(xcolor->pixel, &mbPtr->userPaneBackground); + + return false; +} diff --git a/macosx/tkMacOSXMenus.c b/macosx/tkMacOSXMenus.c new file mode 100644 index 0000000..f3aa259 --- /dev/null +++ b/macosx/tkMacOSXMenus.c @@ -0,0 +1,325 @@ +/* + * tkMacOSXMenus.c -- + * + * These calls set up and manage the menubar for the + * Macintosh version of Tk. + * + * Copyright (c) 1995-1996 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkMacOSXMenus.c,v 1.2 2002/08/31 06:12:30 das Exp $ + */ + +#include "tk.h" +#include "tkInt.h" +#include "tkMacOSXInt.h" + +/* + * The define Status defined by Xlib.h conflicts with the function Status + * defined by Devices.h. We undefine it here to compile. + */ +#undef Status +#include <Carbon/Carbon.h> + +#define kAppleMenu 256 +#define kAppleAboutItem 1 +#define kFileMenu 2 +#define kEditMenu 3 + +#define kSourceItem 1 +#define kCloseItem 2 +#define kQuitItem 4 + +#define EDIT_CUT 1 +#define EDIT_COPY 2 +#define EDIT_PASTE 3 +#define EDIT_CLEAR 4 + +MenuRef tkAppleMenu; +MenuRef tkFileMenu; +MenuRef tkEditMenu; + +static Tcl_Interp * gInterp; /* Interpreter for this application. */ + +static void GenerateEditEvent _ANSI_ARGS_((int flag)); +static void SourceDialog _ANSI_ARGS_((void)); + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXHandleMenuSelect -- + * + * Handles events that occur in the Menu bar. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXHandleMenuSelect( + long mResult, + int optionKeyPressed) +{ + short theItem = LoWord(mResult); + short theMenu = HiWord(mResult); + Tk_Window tkwin; + Window window; + TkDisplay *dispPtr; + + if (mResult == 0) { + TkMacOSXHandleTearoffMenu(); + TkMacOSXClearMenubarActive(); + return; + } + + switch (theMenu) { + case kAppleMenu: + switch (theItem) { + case kAppleAboutItem: + { + Tcl_CmdInfo dummy; + if (optionKeyPressed || gInterp == NULL || + Tcl_GetCommandInfo(gInterp, + "tkAboutDialog", &dummy) == 0) { + TkAboutDlg(); + } else { + Tcl_Eval(gInterp, "tkAboutDialog"); + } + break; + } + } + break; + case kFileMenu: + switch (theItem) { + case kSourceItem: + /* TODO: source script */ + SourceDialog(); + break; + case kCloseItem: + /* Send close event */ + window = TkMacOSXGetXWindow(FrontNonFloatingWindow()); + dispPtr = TkGetDisplayList(); + tkwin = Tk_IdToWindow(dispPtr->display, window); + TkGenWMDestroyEvent(tkwin); + break; + case kQuitItem: + /* Exit */ + if (optionKeyPressed || gInterp == NULL) { + Tcl_Exit(0); + } else { + Tcl_Eval(gInterp, "exit"); + } + break; + } + break; + case kEditMenu: + /* + * This implementation just send keysyms + * the Tk thinks are associated with function keys that + * do Cut, Copy & Paste on a Sun keyboard. + */ + GenerateEditEvent(theItem); + break; + default: + TkMacOSXDispatchMenuEvent(theMenu, theItem); + TkMacOSXClearMenubarActive(); + break; + } + /* + * Finally we unhighlight the menu. + */ + HiliteMenu(0); +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXInitMenus -- + * + * This procedure initializes the Macintosh menu bar. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXInitMenus( + Tcl_Interp *interp) +{ + gInterp = interp; + + /* + * At this point, InitMenus() should have already been called. + */ + + if (TkMacOSXUseMenuID(256) != TCL_OK) { + panic("Menu ID 256 is already in use!"); + } + tkAppleMenu = NewMenu(256, "\p\024"); + if (tkAppleMenu == NULL) { + panic("memory - menus"); + } + InsertMenu(tkAppleMenu, 0); + AppendMenu(tkAppleMenu, "\pAbout Tcl & TkÉ"); + AppendMenu(tkAppleMenu, "\p(-"); + /* Not necessary in Carbon: + AppendResMenu(tkAppleMenu, 'DRVR'); + */ + + if (TkMacOSXUseMenuID(kFileMenu) != TCL_OK) { + panic("Menu ID %d is already in use!", kFileMenu); + } + tkFileMenu = NewMenu(kFileMenu, "\pFile"); + if (tkFileMenu == NULL) { + panic("memory - menus"); + } + InsertMenu(tkFileMenu, 0); + AppendMenu(tkFileMenu, "\pSourceÉ"); + AppendMenu(tkFileMenu, "\pClose/W"); + AppendMenu(tkFileMenu, "\p(-"); + AppendMenu(tkFileMenu, "\pQuit/Q"); + + if (TkMacOSXUseMenuID(kEditMenu) != TCL_OK) { + panic("Menu ID %d is already in use!", kEditMenu); + } + tkEditMenu = NewMenu(kEditMenu, "\pEdit"); + if (tkEditMenu == NULL) { + panic("memory - menus"); + } + InsertMenu(tkEditMenu, 0); + AppendMenu(tkEditMenu, "\pCut/X"); + AppendMenu(tkEditMenu, "\pCopy/C"); + AppendMenu(tkEditMenu, "\pPaste/V"); + AppendMenu(tkEditMenu, "\pClear"); + if (TkMacOSXUseMenuID(kHMHelpMenuID) != TCL_OK) { + panic("Help menu ID %s is already in use!", kHMHelpMenuID); + } + + DrawMenuBar(); + TkMacOSXSetHelpMenuItemCount(); + return; +} + +/* + *---------------------------------------------------------------------- + * + * GenerateEditEvent -- + * + * Takes an edit menu item and posts the corasponding a virtual + * event to Tk's event queue. + * + * Results: + * None. + * + * Side effects: + * May place events of queue. + * + *---------------------------------------------------------------------- + */ + +static void +GenerateEditEvent( + int flag) +{ + XVirtualEvent event; + Point where; + Tk_Window tkwin; + Window window; + TkDisplay *dispPtr; + + window = TkMacOSXGetXWindow(FrontNonFloatingWindow()); + dispPtr = TkGetDisplayList(); + tkwin = Tk_IdToWindow(dispPtr->display, window); + tkwin = (Tk_Window) ((TkWindow *) tkwin)->dispPtr->focusPtr; + if (tkwin == NULL) { + return; + } + + event.type = VirtualEvent; + event.serial = Tk_Display(tkwin)->request; + event.send_event = false; + event.display = Tk_Display(tkwin); + event.event = Tk_WindowId(tkwin); + event.root = XRootWindow(Tk_Display(tkwin), 0); + event.subwindow = None; + event.time = TkpGetMS(); + + GetMouse(&where); + tkwin = Tk_TopCoordsToWindow(tkwin, where.h, where.v, + &event.x, &event.y); + LocalToGlobal(&where); + event.x_root = where.h; + event.y_root = where.v; + event.state = TkMacOSXButtonKeyState(); + event.same_screen = true; + + switch (flag) { + case EDIT_CUT: + event.name = Tk_GetUid("Cut"); + break; + case EDIT_COPY: + event.name = Tk_GetUid("Copy"); + break; + case EDIT_PASTE: + event.name = Tk_GetUid("Paste"); + break; + case EDIT_CLEAR: + event.name = Tk_GetUid("Clear"); + break; + } + Tk_QueueWindowEvent((XEvent *) &event, TCL_QUEUE_TAIL); +} + +/* + *---------------------------------------------------------------------- + * + * SourceDialog -- + * + * Presents a dialog to the user for selecting a Tcl file. The + * selected file will be sourced into the main interpreter. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +SourceDialog() +{ + int result; + CONST char *path; + CONST char *openCmd = "tk_getOpenFile -filetypes {\ + {{TCL Scripts} {.tcl} TEXT} {{Text Files} {} TEXT}}"; + + if (gInterp == NULL) { + return; + } + if (Tcl_Eval(gInterp, openCmd) != TCL_OK) { + return; + } + path = Tcl_GetStringResult(gInterp); + if (strlen(path) == 0) { + return; + } + result = Tcl_EvalFile(gInterp, path); + if (result == TCL_ERROR) { + Tcl_BackgroundError(gInterp); + } +} diff --git a/macosx/tkMacOSXMouseEvent.c b/macosx/tkMacOSXMouseEvent.c new file mode 100644 index 0000000..769472c --- /dev/null +++ b/macosx/tkMacOSXMouseEvent.c @@ -0,0 +1,704 @@ +/* + * tkMacOSXMouseEvent.c -- + * + * This file implements functions that decode & handle mouse events + * on MacOS X. + * + * Copyright 2001, Apple Computer, Inc. + * + * 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. + */ + +#include "tkInt.h" +#include <X11/X.h> +#include <X11/Xlib.h> +#include "tkMacOSXEvent.h" +#include "tkMacOSXInt.h" +#include "tkPort.h" +#include "tkMacOSXDebug.h" + +typedef struct { + WindowRef whichWin; + WindowRef activeNonFloating; + WindowPartCode windowPart; + Point global; + Point local; + unsigned int state; + long delta; +} MouseEventData; + +/* + * Declarations of static variables used in this file. + */ + +static int gEatButtonUp = 0; /* 1 if we need to eat the next * up event */ + +/* + * Declarations of functions used only in this file. + */ + +static void BringWindowForward _ANSI_ARGS_((WindowRef wRef)); +static int GeneratePollingEvents(MouseEventData * medPtr); +static int GenerateMouseWheelEvent(MouseEventData * medPtr); + +extern int TkMacOSXGetEatButtonUp(); +extern void TkMacOSXSetEatButtonUp(int f); + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXProcessMouseEvent -- + * + * This routine processes the event in eventPtr, and + * generates the appropriate Tk events from it. + * + * Results: + * True if event(s) are generated - false otherwise. + * + * Side effects: + * Additional events may be place on the Tk event queue. + * + *---------------------------------------------------------------------- + */ + +int +TkMacOSXProcessMouseEvent(TkMacOSXEvent *eventPtr, MacEventStatus * statusPtr) +{ + WindowRef frontWindow; + Tk_Window tkwin; + Point where, where2; + int xOffset, yOffset; + TkDisplay * dispPtr; + Window window; + int status,err; + MouseEventData mouseEventData, * medPtr = &mouseEventData; + KeyMap keyMap; + + switch (eventPtr->eKind) { + case kEventMouseUp: + case kEventMouseDown: + case kEventMouseMoved: + case kEventMouseDragged: + case kEventMouseWheelMoved: + break; + default: + statusPtr->handledByTk = 1; + return 0; + break; + } + statusPtr->handledByTk = 1; + status = GetEventParameter(eventPtr->eventRef, + kEventParamMouseLocation, + typeQDPoint, NULL, + sizeof(where), NULL, + &where); + if (status != noErr) { + fprintf (stderr, "Failed to retrieve mouse location,%d\n", status); + return 0; + } + medPtr->state = 0; + GetKeys(keyMap); + if (keyMap[1] & 2) { + medPtr->state |= LockMask; + } + if (keyMap[1] & 1) { + medPtr->state |= ShiftMask; + } + if (keyMap[1] & 8) { + medPtr->state |= ControlMask; + } + if (keyMap[1] & 32768) { + medPtr->state |= Mod1Mask; /* command key */ + } + if (keyMap[1] & 4) { + medPtr->state |= Mod2Mask; /* option key */ + } + if (eventPtr->eKind == kEventMouseDown + || eventPtr->eKind== kEventMouseDragged ) { + EventMouseButton mouseButton; + if ((status=GetEventParameter(eventPtr->eventRef, + kEventParamMouseButton, + typeMouseButton, NULL, + sizeof(mouseButton), NULL,&mouseButton)) != noErr ) { + fprintf (stderr, "Failed to retrieve mouse button, %d\n", status); + statusPtr->err = 1; + return 0; + } + medPtr->state |= 1 << ((mouseButton-1)+8); + } + + medPtr->windowPart= FindWindow(where, &medPtr->whichWin); + window = TkMacOSXGetXWindow(medPtr->whichWin); + if (medPtr->whichWin != NULL && window == None) { + statusPtr->handledByTk = 0; + return 0; + } + + frontWindow = FrontWindow(); + medPtr->activeNonFloating = ActiveNonFloatingWindow(); + + /* + * The window manager only needs to know about mouse down events + * and sometimes we need to "eat" the mouse up. Otherwise, we + * just pass the event to Tk. + + */ + if (eventPtr->eKind == kEventMouseUp) { + if (TkMacOSXGetEatButtonUp()) { + TkMacOSXSetEatButtonUp(false); + return false; + } + return TkGenerateButtonEvent(where.h, where.v, + window, medPtr->state); + } + if (eventPtr->eKind == kEventMouseWheelMoved) { + if ((status=GetEventParameter(eventPtr->eventRef, + kEventParamMouseWheelDelta, + typeLongInteger, NULL, + sizeof(medPtr->delta), NULL,&medPtr->delta)) != noErr ) { + fprintf (stderr, + "Failed to retrieve mouse wheel delta, %d\n", status); + statusPtr->err = 1; + return false; + } + } + + dispPtr = TkGetDisplayList(); + tkwin = Tk_IdToWindow(dispPtr->display, window); + + if (eventPtr->eKind != kEventMouseDown ) { + /* + * MouseMoved, MouseDragged or kEventMouseWheelMoved + */ + + medPtr->global = where; + medPtr->local = where; + SetPortWindowPort(frontWindow); + GlobalToLocal(&medPtr->local); + if (eventPtr->eKind == kEventMouseWheelMoved ) { + return GenerateMouseWheelEvent(medPtr); + } else { + return GeneratePollingEvents(medPtr); + } + } + + if (medPtr->whichWin && eventPtr->eKind==kEventMouseDown) { + ProcessSerialNumber frontPsn, ourPsn; + Boolean flag; + if ((err=GetFrontProcess(&frontPsn))!=noErr) { + fprintf(stderr, "GetFrontProcess failed, %d\n", err); + statusPtr->err = 1; + return 1; + } + + GetCurrentProcess(&ourPsn); + if ((err=SameProcess(&frontPsn, &ourPsn, &flag))!=noErr) { + fprintf(stderr, "SameProcess failed, %d\n", err); + statusPtr->err = 1; + return 1; + } else { + if (!flag) { + if ((err=SetFrontProcess(&ourPsn)) != noErr) { + fprintf(stderr,"SetFrontProcess failed,%d\n", err); + statusPtr->err = 1; + return 1; + } + } + } + + } + + if (medPtr->whichWin) { + /* + * We got a mouse down in a window + * See if this is the activate click + * This click moves the window forward. We don't want + * the corresponding mouse-up to be reported to the application + * or else it will mess up some Tk scripts. + */ + + if (!(TkpIsWindowFloating(medPtr->whichWin)) + && (medPtr->whichWin != medPtr->activeNonFloating)) { + Tk_Window grabWin = TkMacOSXGetCapture(); + if ((grabWin != NULL) && (grabWin != tkwin)) { + TkWindow * tkw, * grb; + tkw = (TkWindow *)tkwin; + grb = (TkWindow *)grabWin; + SysBeep(1); + return false; + } + TkMacOSXSetEatButtonUp(true); + BringWindowForward(medPtr->whichWin); + return false; + } + } + + switch (medPtr->windowPart) { + case inDrag: + DragWindow(medPtr->whichWin, where, NULL); + where2.h = where2.v = 0; + LocalToGlobal(&where2); + if (EqualPt(where, where2)) { + return false; + } + TkMacOSXWindowOffset(medPtr->whichWin, &xOffset, &yOffset); + where2.h -= xOffset; + where2.v -= yOffset; + TkGenWMConfigureEvent(tkwin, where2.h, where2.v, + -1, -1, TK_LOCATION_CHANGED); + return true; + break; + case inContent: + return TkGenerateButtonEvent(where.h, where.v, + window, medPtr->state); + break; + case inGrow: + /* + * Generally the content region is the domain of Tk + * sub-windows. However, one exception is the grow + * region. A button down in this area will be handled + * by the window manager. Note: this means that Tk + * may not get button down events in this area! + */ + if (TkMacOSXGrowToplevel(medPtr->whichWin, where) == true) { + return true; + } else { + return TkGenerateButtonEvent(where.h, + where.v, window, medPtr->state); + } + break; + case inGoAway: + if (TrackGoAway(medPtr->whichWin,where)) { + if (tkwin == NULL) { + return false; + } + TkGenWMDestroyEvent(tkwin); + return true; + } + return false; + break; + case inMenuBar: + { + int oldMode; + KeyMap theKeys; + + GetKeys(theKeys); + oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); + TkMacOSXClearMenubarActive(); + + /* + * Handle -postcommand + */ + + TkMacOSXPreprocessMenu(); + TkMacOSXHandleMenuSelect(MenuSelect(where), + theKeys[1] & 4); + Tcl_SetServiceMode(oldMode); + return true; /* TODO: may not be on event on queue. */ + } + break; + case inZoomIn: + case inZoomOut: + if (TkMacOSXZoomToplevel(medPtr->whichWin, where, + medPtr->windowPart) == true) { + return true; + } else { + return false; + } + break; + case inCollapseBox: + if ((err = CollapseWindow(medPtr->whichWin, + !IsWindowCollapsed(medPtr->whichWin)))!=noErr) { + fprintf(stderr,"CollapseWindow failed,%d\n", err); + statusPtr->err = 1; + } + break; + default: + return false; + break; + } + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * GeneratePollingEvents -- + * + * This function polls the mouse position and generates X Motion, + * Enter & Leave events. The cursor is also updated at this + * time. + * + * Results: + * True if event(s) are generated - false otherwise. + * + * Side effects: + * Additional events may be place on the Tk event queue. + * The cursor may be changed. + * + *---------------------------------------------------------------------- + */ + +static int +GeneratePollingEvents(MouseEventData * medPtr) +{ + Tk_Window tkwin, rootwin, grabWin; + Window window; + int local_x, local_y; + TkDisplay *dispPtr; + + + if ((!TkpIsWindowFloating(medPtr->whichWin) + && (medPtr->activeNonFloating != medPtr->whichWin))) { + tkwin = NULL; + } else { + window = TkMacOSXGetXWindow(medPtr->whichWin); + dispPtr = TkGetDisplayList(); + rootwin = Tk_IdToWindow(dispPtr->display, window); + if (rootwin == NULL) { + tkwin = NULL; + } else { + tkwin = Tk_TopCoordsToWindow(rootwin, + medPtr->local.h, medPtr->local.v, + &local_x, &local_y); + } + } + + /* + * The following call will generate the appropiate X events and + * adjust any state that Tk must remember. + */ + + grabWin = TkMacOSXGetCapture(); + + if ((tkwin == NULL) && (grabWin != NULL)) { + tkwin = grabWin; + } + Tk_UpdatePointer(tkwin, medPtr->global.h, medPtr->global.v, + medPtr->state); + + + TkMacOSXInstallCursor(0); + + return true; +} + + +/* + *---------------------------------------------------------------------- + * + * BringWindowForward -- + * + * Bring this background window to the front. We also set state + * so Tk thinks the button is currently up. + * + * Results: + * None. + * + * Side effects: + * The window is brought forward. + * + *---------------------------------------------------------------------- + */ + +static void +BringWindowForward(WindowRef wRef) +{ + if (!TkpIsWindowFloating(wRef)) { + if (IsValidWindowPtr(wRef)) + SelectWindow(wRef); + } +} + +static int +GenerateMouseWheelEvent(MouseEventData * medPtr) +{ + Tk_Window tkwin, rootwin, grabWin; + Window window; + int local_x, local_y; + TkDisplay *dispPtr; + TkWindow *winPtr; + XEvent xEvent; + + if ((!TkpIsWindowFloating(medPtr->whichWin) + && (medPtr->activeNonFloating != medPtr->whichWin))) { + tkwin = NULL; + } else { + window = TkMacOSXGetXWindow(medPtr->whichWin); + dispPtr = TkGetDisplayList(); + rootwin = Tk_IdToWindow(dispPtr->display, window); + if (rootwin == NULL) { + tkwin = NULL; + } else { + tkwin = Tk_TopCoordsToWindow(rootwin, + medPtr->local.h, medPtr->local.v, + &local_x, &local_y); + } + } + + /* + * The following call will generate the appropiate X events and + * adjust any state that Tk must remember. + */ + + grabWin = TkMacOSXGetCapture(); + + if ((tkwin == NULL) && (grabWin != NULL)) { + tkwin = grabWin; + } + if (!tkwin) { + return true; + } + winPtr = ( TkWindow *)tkwin; + xEvent.type = MouseWheelEvent; + xEvent.xkey.keycode = medPtr->delta; + xEvent.xany.serial = LastKnownRequestProcessed(winPtr->display); + xEvent.xany.send_event = false; + xEvent.xany.display = winPtr->display; + xEvent.xany.window = Tk_WindowId(winPtr); + Tk_QueueWindowEvent(&xEvent, TCL_QUEUE_TAIL); + + return true; +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXGetEatButtonUp -- + * + * Results: + * Returns the flag indicating if we need to eat the + * next mouse up event + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ +int +TkMacOSXGetEatButtonUp() +{ + return gEatButtonUp; +} + +/* + * TkMacOSXSetEatButtonUp -- + * + * Results: + * None. + * + * Side effects: + * Sets the flag indicating if we need to eat the + * next mouse up event + * + */ +void +TkMacOSXSetEatButtonUp(int f) +{ + gEatButtonUp = f; +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXButtonKeyState -- + * + * Returns the current state of the button & modifier keys. + * + * Results: + * A bitwise inclusive OR of a subset of the following: + * Button1Mask, ShiftMask, LockMask, ControlMask, Mod?Mask, + * Mod?Mask. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +unsigned int +TkMacOSXButtonKeyState() +{ + unsigned int state = 0; + KeyMap theKeys; + + if (Button() & !gEatButtonUp) { + state |= Button1Mask; + } + + GetKeys(theKeys); + + if (theKeys[1] & 2) { + state |= LockMask; + } + + if (theKeys[1] & 1) { + state |= ShiftMask; + } + + if (theKeys[1] & 8) { + state |= ControlMask; + } + + if (theKeys[1] & 32768) { + state |= Mod1Mask; /* command key */ + } + + if (theKeys[1] & 4) { + state |= Mod2Mask; /* option key */ + } + + return state; +} + +/* + *---------------------------------------------------------------------- + * + * XQueryPointer -- + * + * Check the current state of the mouse. This is not a complete + * implementation of this function. It only computes the root + * coordinates and the current mask. + * + * Results: + * Sets root_x_return, root_y_return, and mask_return. Returns + * true on success. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Bool +XQueryPointer( + Display* display, + Window w, + Window* root_return, + Window* child_return, + int* root_x_return, + int* root_y_return, + int* win_x_return, + int* win_y_return, + unsigned int* mask_return) +{ + Point where; + CGrafPtr port; + GDHandle dev; + + GetGWorld(&port,&dev); + GetMouse(&where); + LocalToGlobal(&where); + + *root_x_return = where.h; + *root_y_return = where.v; + *mask_return = TkMacOSXButtonKeyState(); + return True; +} + + +/* + *---------------------------------------------------------------------- + * + * TkGenerateButtonEvent -- + * + * Given a global x & y position and the button key status this + * procedure generates the appropiate X button event. It also + * handles the state changes needed to implement implicit grabs. + * + * Results: + * True if event(s) are generated - false otherwise. + * + * Side effects: + * Additional events may be place on the Tk event queue. + * Grab state may also change. + * + *---------------------------------------------------------------------- + */ + +int +TkGenerateButtonEvent( + int x, /* X location of mouse */ + int y, /* Y location of mouse */ + Window window, /* X Window containing button event. */ + unsigned int state) /* Button Key state suitable for X event */ +{ + WindowRef whichWin, frontWin; + Point where; + Tk_Window tkwin; + int dummy; + TkDisplay *dispPtr; + + /* + * ButtonDown events will always occur in the front + * window. ButtonUp events, however, may occur anywhere + * on the screen. ButtonUp events should only be sent + * to Tk if in the front window or during an implicit grab. + */ + + where.h = x; + where.v = y; + FindWindow(where, &whichWin); + frontWin = FrontNonFloatingWindow(); + + if ((frontWin == NULL) || ((!(TkpIsWindowFloating(whichWin)) + && (frontWin != whichWin)) + && TkMacOSXGetCapture() == NULL)) { + return false; + } + + dispPtr = TkGetDisplayList(); + tkwin = Tk_IdToWindow(dispPtr->display, window); + + GlobalToLocal(&where); + if (tkwin != NULL) { + tkwin = Tk_TopCoordsToWindow(tkwin, where.h, where.v, + &dummy, &dummy); + } + + Tk_UpdatePointer(tkwin, x, y, state); + + return true; +}
\ No newline at end of file diff --git a/macosx/tkMacOSXNotify.c b/macosx/tkMacOSXNotify.c new file mode 100644 index 0000000..c8c5af9 --- /dev/null +++ b/macosx/tkMacOSXNotify.c @@ -0,0 +1,1145 @@ +/* + * tclMacOSXNotify.c -- + * + * This file contains the implementation of a merged + * Carbon/select-based notifier, which is the lowest-level part + * of the Tcl event loop. This file works together with + * ../generic/tclNotify.c. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkMacOSXNotify.c,v 1.2 2002/08/31 06:12:30 das Exp $ + */ + +#include "tclInt.h" +#include "tclPort.h" + +/* FIXME - Why do I need these here? */ + +#undef environ +#include "tkMacOSX.h" +#include "tkMacOSXEvent.h" +#include <signal.h> + +extern TclStubs tclStubs; + +/* + * This structure is used to keep track of the notifier info for a + * a registered file. + */ + +typedef struct FileHandler { + int fd; + int mask; /* Mask of desired events: TCL_READABLE, + * etc. */ + int readyMask; /* Mask of events that have been seen since the + * last time file handlers were invoked for + * this file. */ + Tcl_FileProc *proc; /* Procedure to call, in the style of + * Tcl_CreateFileHandler. */ + ClientData clientData; /* Argument to pass to proc. */ + struct FileHandler *nextPtr;/* Next in list of all files we care about. */ +} FileHandler; + +/* + * The following structure is what is added to the Tcl event queue when + * file handlers are ready to fire. + */ + +typedef struct FileHandlerEvent { + Tcl_Event header; /* Information that is standard for + * all events. */ + int fd; /* File descriptor that is ready. Used + * to find the FileHandler structure for + * the file (can't point directly to the + * FileHandler structure because it could + * go away while the event is queued). */ +} FileHandlerEvent; + +/* + * The following static structure contains the state information for the + * select based implementation of the Tcl notifier. One of these structures + * is created for each thread that is using the notifier. + */ + +typedef struct ThreadSpecificData { + FileHandler *firstFileHandlerPtr; + /* Pointer to head of file handler list. */ + fd_mask checkMasks[3*MASK_SIZE]; + /* This array is used to build up the masks + * to be used in the next call to select. + * Bits are set in response to calls to + * Tcl_CreateFileHandler. */ + fd_mask readyMasks[3*MASK_SIZE]; + /* This array reflects the readable/writable + * conditions that were found to exist by the + * last call to select. */ + int numFdBits; /* Number of valid bits in checkMasks + * (one more than highest fd for which + * Tcl_WatchFile has been called). */ + int isMainLoop; /* Is this the main Carbon Loop (in which case + * we will call RNE in the actual wait... */ +#ifdef TCL_THREADS + int onList; /* True if it is in this list */ + unsigned int pollState; /* pollState is used to implement a polling + * handshake between each thread and the + * notifier thread. Bits defined below. */ + struct ThreadSpecificData *nextPtr, *prevPtr; + /* All threads that are currently waiting on + * an event have their ThreadSpecificData + * structure on a doubly-linked listed formed + * from these pointers. You must hold the + * notifierMutex lock before accessing these + * fields. */ + Tcl_Condition waitCV; /* Any other thread alerts a notifier + * that an event is ready to be processed + * by signaling this condition variable. */ + int eventReady; /* True if an event is ready to be processed. + * Used as condition flag together with + * waitCV above. */ +#endif +} ThreadSpecificData; + +static Tcl_ThreadDataKey dataKey; + +#ifdef TCL_THREADS +/* + * The following static indicates the number of threads that have + * initialized notifiers. + * + * You must hold the notifierMutex lock before accessing this variable. + */ + +static int notifierCount = 0; + +/* + * The following variable points to the head of a doubly-linked list of + * of ThreadSpecificData structures for all threads that are currently + * waiting on an event. + * + * You must hold the notifierMutex lock before accessing this list. + */ + +static ThreadSpecificData *waitingListPtr = NULL; + +/* + * The notifier thread spends all its time in select() waiting for a + * file descriptor associated with one of the threads on the waitingListPtr + * list to do something interesting. But if the contents of the + * waitingListPtr list ever changes, we need to wake up and restart + * the select() system call. You can wake up the notifier thread by + * writing a single byte to the file descriptor defined below. This + * file descriptor is the input-end of a pipe and the notifier thread is + * listening for data on the output-end of the same pipe. Hence writing + * to this file descriptor will cause the select() system call to return + * and wake up the notifier thread. + * + * You must hold the notifierMutex lock before accessing this list. + */ + +static int triggerPipe = -1; + +/* + * The notifierMutex locks access to all of the global notifier state. + */ + +TCL_DECLARE_MUTEX(notifierMutex) + +/* + * The notifier thread signals the notifierCV when it has finished + * initializing the triggerPipe and right before the notifier + * thread terminates. + */ + +static Tcl_Condition notifierCV; + +/* + * The pollState bits + * POLL_WANT is set by each thread before it waits on its condition + * variable. It is checked by the notifier before it does + * select. + * POLL_DONE is set by the notifier if it goes into select after + * seeing POLL_WANT. The idea is to ensure it tries a select + * with the same bits the initial thread had set. + */ +#define POLL_WANT 0x1 +#define POLL_DONE 0x2 + +/* + * This is the thread ID of the notifier thread that does select. + */ +static Tcl_ThreadId notifierThread; + +#endif + +/* + * Static routines defined in this file. + */ + +#ifdef TCL_THREADS +static void NotifierThreadProc _ANSI_ARGS_((ClientData clientData)); +#endif +static int FileHandlerEventProc _ANSI_ARGS_((Tcl_Event *evPtr, + int flags)); + +void TkMacOSXSetTimer(Tcl_Time *timePtr); +void TkMacOSXCreateFileHandler(int fd, int mask, Tcl_FileProc *proc, ClientData clientData); +void TkMacOSXDeleteFileHandler(int fd); +int TkMacOSXWaitForEvent(Tcl_Time *timePtr); +void TkMacOSXAlertNotifier(ClientData clientData); +ClientData TkMacOSXInitNotifier(); +void TkMacOSXFinalizeNotifier(ClientData clientData); +void TkMacOSXServiceModeHook(int mode); +EventRef TkMacOSXCreateFakeEvent (); +/* + *---------------------------------------------------------------------- + * + * TkMacOSXSetupTkNotifier -- + * + * Replaces the Tcl notifier (from tclUnixNotfy.c) with + * the Mac notifier that melds the Unix select based notifer + * with the Carbon event handling side of the Tk notifier. + * + * Results: + * Replaces the notifier callbacks with MacOS X specific ones. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +Tk_MacOSXSetupTkNotifier() +{ + Tcl_NotifierProcs macNotifierProcs = { + TkMacOSXSetTimer, + TkMacOSXWaitForEvent, + TkMacOSXCreateFileHandler, + TkMacOSXDeleteFileHandler, + TkMacOSXInitNotifier, + TkMacOSXFinalizeNotifier, + TkMacOSXAlertNotifier, + TkMacOSXServiceModeHook + }; + + Tcl_SetNotifier(&macNotifierProcs); + + /* + * Tcl_SetNotifier doesn't call the TclInitNotifier + * so we call it now. If we don't do this the + * ThreadSpecificData will keep a pointer to the original + * InitNotifier. See tclNotify.c:TclInitNotifier(). + */ + + TclInitNotifier(); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_InitNotifier -- + * + * Initializes the platform specific notifier state. + * + * Results: + * Returns a handle to the notifier state for this thread.. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +ClientData +TkMacOSXInitNotifier() +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + +#ifdef TCL_THREADS + tsdPtr->eventReady = 0; + + /* + * Start the Notifier thread if necessary. + */ + + Tcl_MutexLock(¬ifierMutex); + if (notifierCount == 0) { + if (Tcl_CreateThread(¬ifierThread, NotifierThreadProc, NULL, + TCL_THREAD_STACK_DEFAULT, TCL_THREAD_NOFLAGS) != TCL_OK) { + panic("Tcl_InitNotifier: unable to start notifier thread"); + } + } + notifierCount++; + + if (GetCurrentEventLoop() == GetMainEventLoop()) { + tsdPtr->isMainLoop = 1; + } else { + tsdPtr->isMainLoop = 0; + } + + /* + * Wait for the notifier pipe to be created. + */ + + while (triggerPipe < 0) { + Tcl_ConditionWait(¬ifierCV, ¬ifierMutex, NULL); + } + + Tcl_MutexUnlock(¬ifierMutex); +#endif + return (ClientData) tsdPtr; +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_FinalizeNotifier -- + * + * This function is called to cleanup the notifier state before + * a thread is terminated. + * + * Results: + * None. + * + * Side effects: + * May terminate the background notifier thread if this is the + * last notifier instance. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXFinalizeNotifier(clientData) + ClientData clientData; /* Not used. */ +{ +#ifdef TCL_THREADS + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + Tcl_MutexLock(¬ifierMutex); + notifierCount--; + + /* + * If this is the last thread to use the notifier, close the notifier + * pipe and wait for the background thread to terminate. + */ + + if (notifierCount == 0) { + if (triggerPipe < 0) { + panic("Tcl_FinalizeNotifier: notifier pipe not initialized"); + } + + /* + * Send "q" message to the notifier thread so that it will + * terminate. The notifier will return from its call to select() + * and notice that a "q" message has arrived, it will then close + * its side of the pipe and terminate its thread. Note the we can + * not just close the pipe and check for EOF in the notifier + * thread because if a background child process was created with + * exec, select() would not register the EOF on the pipe until the + * child processes had terminated. [Bug: 4139] + */ + write(triggerPipe, "q", 1); + close(triggerPipe); + + Tcl_ConditionWait(¬ifierCV, ¬ifierMutex, NULL); + } + + /* + * Clean up any synchronization objects in the thread local storage. + */ + + Tcl_ConditionFinalize(&(tsdPtr->waitCV)); + + Tcl_MutexUnlock(¬ifierMutex); +#endif +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_AlertNotifier -- + * + * Wake up the specified notifier from any thread. This routine + * is called by the platform independent notifier code whenever + * the Tcl_ThreadAlert routine is called. This routine is + * guaranteed not to be called on a given notifier after + * Tcl_FinalizeNotifier is called for that notifier. + * + * Results: + * None. + * + * Side effects: + * Signals the notifier condition variable for the specified + * notifier. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXAlertNotifier(clientData) + ClientData clientData; +{ +#ifdef TCL_THREADS + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) clientData; + Tcl_MutexLock(¬ifierMutex); + tsdPtr->eventReady = 1; + Tcl_ConditionNotify(&tsdPtr->waitCV); + Tcl_MutexUnlock(¬ifierMutex); +#endif +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_SetTimer -- + * + * This procedure sets the current notifier timer value. This + * interface is not implemented in this notifier because we are + * always running inside of Tcl_DoOneEvent. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXSetTimer(timePtr) + Tcl_Time *timePtr; /* Timeout value, may be NULL. */ +{ + /* + * The interval timer doesn't do anything in this implementation, + * because the only event loop is via Tcl_DoOneEvent, which passes + * timeout values to Tcl_WaitForEvent. + */ + +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_ServiceModeHook -- + * + * This function is invoked whenever the service mode changes. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXServiceModeHook(mode) + int mode; /* Either TCL_SERVICE_ALL, or + * TCL_SERVICE_NONE. */ +{ +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_CreateFileHandler -- + * + * This procedure registers a file handler with the select notifier. + * + * Results: + * None. + * + * Side effects: + * Creates a new file handler structure. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXCreateFileHandler(fd, mask, proc, clientData) + int fd; /* Handle of stream to watch. */ + int mask; /* OR'ed combination of TCL_READABLE, + * TCL_WRITABLE, and TCL_EXCEPTION: + * indicates conditions under which + * proc should be called. */ + Tcl_FileProc *proc; /* Procedure to call for each + * selected event. */ + ClientData clientData; /* Arbitrary data to pass to proc. */ +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + FileHandler *filePtr; + int index, bit; + + for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL; + filePtr = filePtr->nextPtr) { + if (filePtr->fd == fd) { + break; + } + } + if (filePtr == NULL) { + filePtr = (FileHandler*) ckalloc(sizeof(FileHandler)); + filePtr->fd = fd; + filePtr->readyMask = 0; + filePtr->nextPtr = tsdPtr->firstFileHandlerPtr; + tsdPtr->firstFileHandlerPtr = filePtr; + } + filePtr->proc = proc; + filePtr->clientData = clientData; + filePtr->mask = mask; + + /* + * Update the check masks for this file. + */ + + index = fd/(NBBY*sizeof(fd_mask)); + bit = 1 << (fd%(NBBY*sizeof(fd_mask))); + if (mask & TCL_READABLE) { + tsdPtr->checkMasks[index] |= bit; + } else { + tsdPtr->checkMasks[index] &= ~bit; + } + if (mask & TCL_WRITABLE) { + (tsdPtr->checkMasks+MASK_SIZE)[index] |= bit; + } else { + (tsdPtr->checkMasks+MASK_SIZE)[index] &= ~bit; + } + if (mask & TCL_EXCEPTION) { + (tsdPtr->checkMasks+2*(MASK_SIZE))[index] |= bit; + } else { + (tsdPtr->checkMasks+2*(MASK_SIZE))[index] &= ~bit; + } + if (tsdPtr->numFdBits <= fd) { + tsdPtr->numFdBits = fd+1; + } +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_DeleteFileHandler -- + * + * Cancel a previously-arranged callback arrangement for + * a file. + * + * Results: + * None. + * + * Side effects: + * If a callback was previously registered on file, remove it. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXDeleteFileHandler(fd) + int fd; /* Stream id for which to remove callback procedure. */ +{ + FileHandler *filePtr, *prevPtr; + int index, bit, i; + unsigned long flags; + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + /* + * Find the entry for the given file (and return if there isn't one). + */ + + for (prevPtr = NULL, filePtr = tsdPtr->firstFileHandlerPtr; ; + prevPtr = filePtr, filePtr = filePtr->nextPtr) { + if (filePtr == NULL) { + return; + } + if (filePtr->fd == fd) { + break; + } + } + + /* + * Update the check masks for this file. + */ + + index = fd/(NBBY*sizeof(fd_mask)); + bit = 1 << (fd%(NBBY*sizeof(fd_mask))); + + if (filePtr->mask & TCL_READABLE) { + tsdPtr->checkMasks[index] &= ~bit; + } + if (filePtr->mask & TCL_WRITABLE) { + (tsdPtr->checkMasks+MASK_SIZE)[index] &= ~bit; + } + if (filePtr->mask & TCL_EXCEPTION) { + (tsdPtr->checkMasks+2*(MASK_SIZE))[index] &= ~bit; + } + + /* + * Find current max fd. + */ + + if (fd+1 == tsdPtr->numFdBits) { + for (tsdPtr->numFdBits = 0; index >= 0; index--) { + flags = tsdPtr->checkMasks[index] + | (tsdPtr->checkMasks+MASK_SIZE)[index] + | (tsdPtr->checkMasks+2*(MASK_SIZE))[index]; + if (flags) { + for (i = (NBBY*sizeof(fd_mask)); i > 0; i--) { + if (flags & (((unsigned long)1) << (i-1))) { + break; + } + } + tsdPtr->numFdBits = index * (NBBY*sizeof(fd_mask)) + i; + break; + } + } + } + + /* + * Clean up information in the callback record. + */ + + if (prevPtr == NULL) { + tsdPtr->firstFileHandlerPtr = filePtr->nextPtr; + } else { + prevPtr->nextPtr = filePtr->nextPtr; + } + ckfree((char *) filePtr); +} + +/* + *---------------------------------------------------------------------- + * + * FileHandlerEventProc -- + * + * This procedure is called by Tcl_ServiceEvent when a file event + * reaches the front of the event queue. This procedure is + * responsible for actually handling the event by invoking the + * callback for the file handler. + * + * Results: + * Returns 1 if the event was handled, meaning it should be removed + * from the queue. Returns 0 if the event was not handled, meaning + * it should stay on the queue. The only time the event isn't + * handled is if the TCL_FILE_EVENTS flag bit isn't set. + * + * Side effects: + * Whatever the file handler's callback procedure does. + * + *---------------------------------------------------------------------- + */ + +static int +FileHandlerEventProc(evPtr, flags) + Tcl_Event *evPtr; /* Event to service. */ + int flags; /* Flags that indicate what events to + * handle, such as TCL_FILE_EVENTS. */ +{ + int mask; + FileHandler *filePtr; + FileHandlerEvent *fileEvPtr = (FileHandlerEvent *) evPtr; + ThreadSpecificData *tsdPtr; + + if (!(flags & TCL_FILE_EVENTS)) { + return 0; + } + + /* + * Search through the file handlers to find the one whose handle matches + * the event. We do this rather than keeping a pointer to the file + * handler directly in the event, so that the handler can be deleted + * while the event is queued without leaving a dangling pointer. + */ + + tsdPtr = TCL_TSD_INIT(&dataKey); + for (filePtr = tsdPtr->firstFileHandlerPtr; filePtr != NULL; + filePtr = filePtr->nextPtr) { + if (filePtr->fd != fileEvPtr->fd) { + continue; + } + + /* + * The code is tricky for two reasons: + * 1. The file handler's desired events could have changed + * since the time when the event was queued, so AND the + * ready mask with the desired mask. + * 2. The file could have been closed and re-opened since + * the time when the event was queued. This is why the + * ready mask is stored in the file handler rather than + * the queued event: it will be zeroed when a new + * file handler is created for the newly opened file. + */ + + mask = filePtr->readyMask & filePtr->mask; + filePtr->readyMask = 0; + if (mask != 0) { + (*filePtr->proc)(filePtr->clientData, mask); + } + break; + } + return 1; +} + +void +DoActualWait(timePtr) + Tcl_Time *timePtr; /* Maximum block time, or NULL. */ +{ + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + if (!tsdPtr->isMainLoop) { + Tcl_ConditionWait(&tsdPtr->waitCV, ¬ifierMutex, timePtr); + } else { + EventRef eventRef; + EventTime waitTime; + Tcl_MutexUnlock(¬ifierMutex); + + if (timePtr == NULL) { + waitTime = kEventDurationForever; + } else { + waitTime = timePtr->sec * kEventDurationSecond + + timePtr->usec * kEventDurationMicrosecond; + } + ReceiveNextEvent(0, NULL, waitTime, false, &eventRef); + Tcl_MutexLock(¬ifierMutex); + } +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_WaitForEvent -- + * + * This function is called by Tcl_DoOneEvent to wait for new + * events on the message queue. If the block time is 0, then + * Tcl_WaitForEvent just polls without blocking. + * + * Results: + * Returns -1 if the select would block forever, otherwise + * returns 0. + * + * Side effects: + * Queues file events that are detected by the select. + * + *---------------------------------------------------------------------- + */ + +int +TkMacOSXWaitForEvent(timePtr) + Tcl_Time *timePtr; /* Maximum block time, or NULL. */ +{ + FileHandler *filePtr; + FileHandlerEvent *fileEvPtr; + struct timeval timeout, *timeoutPtr; + int bit, index, mask; +#ifdef TCL_THREADS + int waitForFiles; +#else + int numFound; +#endif + + ThreadSpecificData *tsdPtr = TCL_TSD_INIT(&dataKey); + + /* + * Set up the timeout structure. Note that if there are no events to + * check for, we return with a negative result rather than blocking + * forever. + */ + + if (timePtr) { + timeout.tv_sec = timePtr->sec; + timeout.tv_usec = timePtr->usec; + timeoutPtr = &timeout; +#ifndef TCL_THREADS + } else if (tsdPtr->numFdBits == 0) { + /* + * If there are no threads, no timeout, and no fds registered, + * then there are no events possible and we must avoid deadlock. + * Note that this is not entirely correct because there might + * be a signal that could interrupt the select call, but we + * don't handle that case if we aren't using threads. + */ + + return -1; +#endif + } else { + timeoutPtr = NULL; + } + +#ifdef TCL_THREADS + /* + * Place this thread on the list of interested threads, signal the + * notifier thread, and wait for a response or a timeout. + */ + + Tcl_MutexLock(¬ifierMutex); + + waitForFiles = (tsdPtr->numFdBits > 0); + if (timePtr != NULL && timePtr->sec == 0 && timePtr->usec == 0) { + /* + * Cannot emulate a polling select with a polling condition variable. + * Instead, pretend to wait for files and tell the notifier + * thread what we are doing. The notifier thread makes sure + * it goes through select with its select mask in the same state + * as ours currently is. We block until that happens. + */ + + waitForFiles = 1; + tsdPtr->pollState = POLL_WANT; + timePtr = NULL; + } else { + tsdPtr->pollState = 0; + } + + if (waitForFiles) { + /* + * Add the ThreadSpecificData structure of this thread to the list + * of ThreadSpecificData structures of all threads that are waiting + * on file events. + */ + + + tsdPtr->nextPtr = waitingListPtr; + if (waitingListPtr) { + waitingListPtr->prevPtr = tsdPtr; + } + tsdPtr->prevPtr = 0; + waitingListPtr = tsdPtr; + tsdPtr->onList = 1; + + write(triggerPipe, "", 1); + } + + memset((VOID *) tsdPtr->readyMasks, 0, 3*MASK_SIZE*sizeof(fd_mask)); + + if (!tsdPtr->eventReady) { + DoActualWait(timePtr); + } + tsdPtr->eventReady = 0; + + if (waitForFiles && tsdPtr->onList) { + /* + * Remove the ThreadSpecificData structure of this thread from the + * waiting list. Alert the notifier thread to recompute its select + * masks - skipping this caused a hang when trying to close a pipe + * which the notifier thread was still doing a select on. + */ + + if (tsdPtr->prevPtr) { + tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr; + } else { + waitingListPtr = tsdPtr->nextPtr; + } + if (tsdPtr->nextPtr) { + tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr; + } + tsdPtr->nextPtr = tsdPtr->prevPtr = NULL; + tsdPtr->onList = 0; + write(triggerPipe, "", 1); + } + + +#else + memcpy((VOID *) tsdPtr->readyMasks, (VOID *) tsdPtr->checkMasks, + 3*MASK_SIZE*sizeof(fd_mask)); + numFound = select(tsdPtr->numFdBits, + (SELECT_MASK *) &tsdPtr->readyMasks[0], + (SELECT_MASK *) &tsdPtr->readyMasks[MASK_SIZE], + (SELECT_MASK *) &tsdPtr->readyMasks[2*MASK_SIZE], timeoutPtr); + + /* + * Some systems don't clear the masks after an error, so + * we have to do it here. + */ + + if (numFound == -1) { + memset((VOID *) tsdPtr->readyMasks, 0, 3*MASK_SIZE*sizeof(fd_mask)); + } +#endif + + /* + * Queue all detected file events before returning. + */ + + for (filePtr = tsdPtr->firstFileHandlerPtr; (filePtr != NULL); + filePtr = filePtr->nextPtr) { + index = filePtr->fd / (NBBY*sizeof(fd_mask)); + bit = 1 << (filePtr->fd % (NBBY*sizeof(fd_mask))); + mask = 0; + + if (tsdPtr->readyMasks[index] & bit) { + mask |= TCL_READABLE; + } + if ((tsdPtr->readyMasks+MASK_SIZE)[index] & bit) { + mask |= TCL_WRITABLE; + } + if ((tsdPtr->readyMasks+2*(MASK_SIZE))[index] & bit) { + mask |= TCL_EXCEPTION; + } + + if (!mask) { + continue; + } + + /* + * Don't bother to queue an event if the mask was previously + * non-zero since an event must still be on the queue. + */ + + if (filePtr->readyMask == 0) { + fileEvPtr = (FileHandlerEvent *) ckalloc( + sizeof(FileHandlerEvent)); + fileEvPtr->header.proc = FileHandlerEventProc; + fileEvPtr->fd = filePtr->fd; + Tcl_QueueEvent((Tcl_Event *) fileEvPtr, TCL_QUEUE_TAIL); + } + filePtr->readyMask = mask; + } + + /* + * Also queue the Mac Events found... + */ + +#ifdef TCL_THREADS + Tcl_MutexUnlock(¬ifierMutex); +#endif + + if (tsdPtr->isMainLoop) { + TkMacOSXCountAndProcessMacEvents(); + } + + return 0; +} + +#ifdef TCL_THREADS +/* + *---------------------------------------------------------------------- + * + * NotifierThreadProc -- + * + * This routine is the initial (and only) function executed by the + * special notifier thread. Its job is to wait for file descriptors + * to become readable or writable or to have an exception condition + * and then to notify other threads who are interested in this + * information by signalling a condition variable. Other threads + * can signal this notifier thread of a change in their interests + * by writing a single byte to a special pipe that the notifier + * thread is monitoring. + * + * Result: + * None. Once started, this routine never exits. It dies with + * the overall process. + * + * Side effects: + * The trigger pipe used to signal the notifier thread is created + * when the notifier thread first starts. + * + *---------------------------------------------------------------------- + */ + +static void +NotifierThreadProc(clientData) + ClientData clientData; /* Not used. */ +{ + ThreadSpecificData *tsdPtr; + fd_mask masks[3*MASK_SIZE]; + long *maskPtr = (long *)masks; /* masks[] cast to type long[] */ + int fds[2]; + int i, status, index, bit, numFdBits, found, receivePipe, word; + struct timeval poll = {0., 0.}, *timePtr; + int maskSize = 3 * ((MASK_SIZE) / sizeof(long)) * sizeof(fd_mask); + char buf[2]; + + if (pipe(fds) != 0) { + panic("NotifierThreadProc: could not create trigger pipe."); + } + + receivePipe = fds[0]; + +#ifndef USE_FIONBIO + status = fcntl(receivePipe, F_GETFL); + status |= O_NONBLOCK; + if (fcntl(receivePipe, F_SETFL, status) < 0) { + panic("NotifierThreadProc: could not make receive pipe non blocking."); + } + status = fcntl(fds[1], F_GETFL); + status |= O_NONBLOCK; + if (fcntl(fds[1], F_SETFL, status) < 0) { + panic("NotifierThreadProc: could not make trigger pipe non blocking."); + } +#else + if (ioctl(receivePipe, (int) FIONBIO, &status) < 0) { + panic("NotifierThreadProc: could not make receive pipe non blocking."); + } + if (ioctl(fds[1], (int) FIONBIO, &status) < 0) { + panic("NotifierThreadProc: could not make trigger pipe non blocking."); + } +#endif + + /* + * Install the write end of the pipe into the global variable. + */ + + Tcl_MutexLock(¬ifierMutex); + triggerPipe = fds[1]; + + /* + * Signal any threads that are waiting. + */ + + Tcl_ConditionNotify(¬ifierCV); + Tcl_MutexUnlock(¬ifierMutex); + + /* + * Look for file events and report them to interested threads. + */ + + while (1) { + /* + * Set up the select mask to include the receive pipe. + */ + + memset((VOID *)masks, 0, 3*MASK_SIZE*sizeof(fd_mask)); + numFdBits = receivePipe + 1; + index = receivePipe / (NBBY*sizeof(fd_mask)); + bit = 1 << (receivePipe % (NBBY*sizeof(fd_mask))); + masks[index] |= bit; + + /* + * Add in the check masks from all of the waiting notifiers. + */ + + Tcl_MutexLock(¬ifierMutex); + timePtr = NULL; + for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) { + for (i = 0; i < maskSize; i++) { + maskPtr[i] |= ((long*)tsdPtr->checkMasks)[i]; + } + if (tsdPtr->numFdBits > numFdBits) { + numFdBits = tsdPtr->numFdBits; + } + if (tsdPtr->pollState & POLL_WANT) { + /* + * Here we make sure we go through select() with the same + * mask bits that were present when the thread tried to poll. + */ + + tsdPtr->pollState |= POLL_DONE; + timePtr = &poll; + } + } + Tcl_MutexUnlock(¬ifierMutex); + + maskSize = 3 * ((MASK_SIZE) / sizeof(long)) * sizeof(fd_mask); + + if (select(numFdBits, (SELECT_MASK *) &masks[0], + (SELECT_MASK *) &masks[MASK_SIZE], + (SELECT_MASK *) &masks[2*MASK_SIZE], timePtr) == -1) { + /* + * Try again immediately on an error. + */ + + continue; + } + + /* + * Alert any threads that are waiting on a ready file descriptor. + */ + + Tcl_MutexLock(¬ifierMutex); + for (tsdPtr = waitingListPtr; tsdPtr; tsdPtr = tsdPtr->nextPtr) { + found = 0; + + for (i = 0; i < maskSize; i++) { + word = maskPtr[i] & ((long*)tsdPtr->checkMasks)[i]; + found |= word; + (((long*)(tsdPtr->readyMasks))[i]) = word; + } + if (found || (tsdPtr->pollState & POLL_DONE)) { + if (tsdPtr->onList) { + /* + * Remove the ThreadSpecificData structure of this + * thread from the waiting list. This prevents us from + * continuously spining on select until the other + * threads runs and services the file event. + */ + + if (tsdPtr->prevPtr) { + tsdPtr->prevPtr->nextPtr = tsdPtr->nextPtr; + } else { + waitingListPtr = tsdPtr->nextPtr; + } + if (tsdPtr->nextPtr) { + tsdPtr->nextPtr->prevPtr = tsdPtr->prevPtr; + } + tsdPtr->nextPtr = tsdPtr->prevPtr = NULL; + tsdPtr->onList = 0; + tsdPtr->pollState = 0; + } + tsdPtr->eventReady = 1; + if (tsdPtr->isMainLoop) { + /* We need to wake up the main loop, and let it have the event. */ + EventRef fakeEvent = TkMacOSXCreateFakeEvent(); + PostEventToQueue(GetMainEventQueue(), fakeEvent, kEventPriorityHigh); + ReleaseEvent(fakeEvent); + } else { + Tcl_ConditionNotify(&tsdPtr->waitCV); + } + } + } + Tcl_MutexUnlock(¬ifierMutex); + + /* + * Consume the next byte from the notifier pipe if the pipe was + * readable. Note that there may be multiple bytes pending, but + * to avoid a race condition we only read one at a time. + */ + + if (masks[index] & bit) { + i = read(receivePipe, buf, 1); + + if ((i == 0) || ((i == 1) && (buf[0] == 'q'))) { + /* + * Someone closed the write end of the pipe or sent us a + * Quit message [Bug: 4139] and then closed the write end + * of the pipe so we need to shut down the notifier thread. + */ + + break; + } + } + } + + /* + * Clean up the read end of the pipe and signal any threads waiting on + * termination of the notifier thread. + */ + + close(receivePipe); + Tcl_MutexLock(¬ifierMutex); + triggerPipe = -1; + Tcl_ConditionNotify(¬ifierCV); + Tcl_MutexUnlock(¬ifierMutex); +} +#endif + +EventRef +TkMacOSXCreateFakeEvent () +{ + EventKind eKind; + EventClass eClass; + EventTime eTime; + EventRef eventRef; + EventAttributes flags; + eClass=kEventClassWish; + eKind = 0xffff; + eTime =GetLastUserEventTime() + 0.001; + flags=kEventAttributeUserEvent; + if (CreateEvent(NULL,eClass,eKind,eTime,flags,&eventRef)!=noErr) { + fprintf(stderr,"CreateEvent failed\n"); + return NULL; + } + return eventRef; +} diff --git a/macosx/tkMacOSXPort.h b/macosx/tkMacOSXPort.h new file mode 100644 index 0000000..c59a005 --- /dev/null +++ b/macosx/tkMacOSXPort.h @@ -0,0 +1,154 @@ +/* + * tkMacOSXPort.h -- + * + * This file is included by all of the Tk C files. It contains + * information that may be configuration-dependent, such as + * #includes for system include files and a few other things. + * + * Copyright (c) 1994-1996 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkMacOSXPort.h,v 1.2 2002/08/31 06:12:30 das Exp $ + */ + +#ifndef _TKMACPORT +#define _TKMACPORT + +/* + * Macro to use instead of "void" for arguments that must have + * type "void *" in ANSI C; maps them to type "char *" in + * non-ANSI systems. This macro may be used in some of the include + * files below, which is why it is defined here. + */ + +#ifndef VOID +# ifdef __STDC__ +# define VOID void +# else +# define VOID char +# endif +#endif + +#ifndef _TCL +# include <tcl.h> +#endif + +#include <time.h> +#include <stdlib.h> +#include <string.h> +#include "tclMath.h" +#include <ctype.h> +#include <limits.h> + +#include <X11/Xlib.h> +#include <X11/cursorfont.h> +#include <X11/keysym.h> +#include <X11/Xatom.h> +#include <X11/Xfuncproto.h> +#include <X11/Xutil.h> +#include "tkIntXlibDecls.h" + +/* + * Not all systems declare the errno variable in errno.h. so this + * file does it explicitly. + */ + +extern int errno; + +/* + * Define "NBBY" (number of bits per byte) if it's not already defined. + */ + +#ifndef NBBY +# define NBBY 8 +#endif + +/* + * Declarations for various library procedures that may not be declared + * in any other header file. + */ + +#ifndef panic /* In a stubs-aware setting, this could confuse the #define */ +extern void panic _ANSI_ARGS_(TCL_VARARGS(char *, string)); +#endif +#ifndef strcasecmp +extern int strcasecmp _ANSI_ARGS_((CONST char *s1, + CONST char *s2)); +#endif +#ifndef strncasecmp +extern int strncasecmp _ANSI_ARGS_((CONST char *s1, + CONST char *s2, size_t n)); +#endif +/* + * Defines for X functions that are used by Tk but are treated as + * no-op functions on the Macintosh. + */ + +#define XFlush(display) +#define XFree(data) {if ((data) != NULL) ckfree((char *) (data));} +#define XGrabServer(display) +#define XNoOp(display) {display->request++;} +#define XUngrabServer(display) +#define XSynchronize(display, bool) {display->request++;} +#define XSync(display, bool) {display->request++;} +#define XVisualIDFromVisual(visual) (visual->visualid) + +/* + * The following functions are not used on the Mac, so we stub them out. + */ + +#define TkFreeWindowId(dispPtr,w) +#define TkInitXId(dispPtr) +#define TkpButtonSetDefaults(specPtr) {} +#define TkpCmapStressed(tkwin,colormap) (0) +#define TkpFreeColor(tkColPtr) +#define TkSetPixmapColormap(p,c) {} +#define TkpSync(display) + +/* + * The following macro returns the pixel value that corresponds to the + * RGB values in the given XColor structure. + */ + +#define PIXEL_MAGIC ((unsigned char) 0x69) +#define TkpGetPixel(p) ((((((PIXEL_MAGIC << 8) \ + | (((p)->red >> 8) & 0xff)) << 8) \ + | (((p)->green >> 8) & 0xff)) << 8) \ + | (((p)->blue >> 8) & 0xff)) + +/* + * This macro stores a representation of the window handle in a string. + * This should perhaps use the real size of an XID. + */ + +#define TkpPrintWindowId(buf,w) \ + sprintf((buf), "0x%x", (unsigned int) (w)) + +/* + * TkpScanWindowId is just an alias for Tcl_GetInt on Unix. + */ + +#define TkpScanWindowId(i,s,wp) \ + Tcl_GetInt((i),(s),(int *) (wp)) + +/* + * Magic pixel values for dynamic (or active) colors. + */ + +#define HIGHLIGHT_PIXEL 31 +#define HIGHLIGHT_TEXT_PIXEL 33 +#define CONTROL_TEXT_PIXEL 35 +#define CONTROL_BODY_PIXEL 37 +#define CONTROL_FRAME_PIXEL 39 +#define WINDOW_BODY_PIXEL 41 +#define MENU_ACTIVE_PIXEL 43 +#define MENU_ACTIVE_TEXT_PIXEL 45 +#define MENU_BACKGROUND_PIXEL 47 +#define MENU_DISABLED_PIXEL 49 +#define MENU_TEXT_PIXEL 51 +#define APPEARANCE_PIXEL 52 + +#endif /* _TKMACPORT */ diff --git a/macosx/tkMacOSXRegion.c b/macosx/tkMacOSXRegion.c new file mode 100644 index 0000000..0fce0c0 --- /dev/null +++ b/macosx/tkMacOSXRegion.c @@ -0,0 +1,252 @@ +/* + * tkMacOSXRegion.c -- + * + * Implements X window calls for manipulating regions + * + * Copyright (c) 1995-1996 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkMacOSXRegion.c,v 1.2 2002/08/31 06:12:30 das Exp $ + */ + +#include "tkInt.h" +#include "tkMacOSXInt.h" +#include "X11/X.h" +#include "X11/Xlib.h" + +#include <Carbon/Carbon.h> +/* +#include <Windows.h> +#include <QDOffscreen.h> +*/ + +/* + * Temporary region that can be reused. + */ +static RgnHandle tmpRgn = NULL; + + +/* + *---------------------------------------------------------------------- + * + * TkCreateRegion -- + * + * Implements the equivelent of the X window function + * XCreateRegion. See X window documentation for more details. + * + * Results: + * Returns an allocated region handle. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TkRegion +TkCreateRegion() +{ + RgnHandle rgn; + rgn = NewRgn(); + return (TkRegion) rgn; +} + +/* + *---------------------------------------------------------------------- + * + * TkDestroyRegion -- + * + * Implements the equivelent of the X window function + * XDestroyRegion. See X window documentation for more details. + * + * Results: + * None. + * + * Side effects: + * Memory is freed. + * + *---------------------------------------------------------------------- + */ + +void +TkDestroyRegion( + TkRegion r) +{ + RgnHandle rgn = (RgnHandle) r; + DisposeRgn(rgn); +} + +/* + *---------------------------------------------------------------------- + * + * TkIntersectRegion -- + * + * Implements the equivilent of the X window function + * XIntersectRegion. See X window documentation for more details. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkIntersectRegion( + TkRegion sra, + TkRegion srb, + TkRegion dr_return) +{ + RgnHandle srcRgnA = (RgnHandle) sra; + RgnHandle srcRgnB = (RgnHandle) srb; + RgnHandle destRgn = (RgnHandle) dr_return; + SectRgn(srcRgnA, srcRgnB, destRgn); +} + +/* + *---------------------------------------------------------------------- + * + * TkUnionRectWithRegion -- + * + * Implements the equivelent of the X window function + * XUnionRectWithRegion. See X window documentation for more + * details. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkUnionRectWithRegion( + XRectangle* rectangle, + TkRegion src_region, + TkRegion dest_region_return) +{ + RgnHandle srcRgn = (RgnHandle) src_region; + RgnHandle destRgn = (RgnHandle) dest_region_return; + + if (tmpRgn == NULL) { + tmpRgn = NewRgn(); + } + SetRectRgn(tmpRgn, rectangle->x, rectangle->y, + rectangle->x + rectangle->width, rectangle->y + rectangle->height); + UnionRgn(srcRgn, tmpRgn, destRgn); +} + +/* + *---------------------------------------------------------------------- + * + * TkRectInRegion -- + * + * Implements the equivelent of the X window function + * XRectInRegion. See X window documentation for more details. + * + * Results: + * Returns one of: RectangleOut, RectangleIn, RectanglePart. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkRectInRegion( + TkRegion region, + int x, + int y, + unsigned int width, + unsigned int height) +{ + RgnHandle rgn = (RgnHandle) region; + RgnHandle rectRgn, destRgn; + int result; + + rectRgn = NewRgn(); + destRgn = NewRgn(); + SetRectRgn(rectRgn, x, y, x + width, y + height); + SectRgn(rgn, rectRgn, destRgn); + if (EmptyRgn(destRgn)) { + result = RectangleOut; + } else if (EqualRgn(rgn, destRgn)) { + result = RectangleIn; + } else { + result = RectanglePart; + } + DisposeRgn(rectRgn); + DisposeRgn(destRgn); + return result; +} + +/* + *---------------------------------------------------------------------- + * + * TkClipBox -- + * + * Implements the equivelent of the X window function XClipBox. + * See X window documentation for more details. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkClipBox( + TkRegion r, + XRectangle* rect_return) +{ + RgnHandle rgn = (RgnHandle) r; + Rect rect; + + GetRegionBounds(rgn,&rect); + + rect_return->x = rect.left; + rect_return->y = rect.top; + rect_return->width = rect.right-rect.left; + rect_return->height = rect.bottom-rect.top; +} + +/* + *---------------------------------------------------------------------- + * + * TkSubtractRegion -- + * + * Implements the equivilent of the X window function + * XSubtractRegion. See X window documentation for more details. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkSubtractRegion( + TkRegion sra, + TkRegion srb, + TkRegion dr_return) +{ + RgnHandle srcRgnA = (RgnHandle) sra; + RgnHandle srcRgnB = (RgnHandle) srb; + RgnHandle destRgn = (RgnHandle) dr_return; + + DiffRgn(srcRgnA, srcRgnB, destRgn); +} diff --git a/macosx/tkMacOSXResource.r b/macosx/tkMacOSXResource.r new file mode 100644 index 0000000..51a19c1 --- /dev/null +++ b/macosx/tkMacOSXResource.r @@ -0,0 +1,502 @@ +/* + * tkMacOSXResources.r -- + * + * This file creates resources for use in a simple shell. + * This is designed to be an example of using the Tcl/Tk + * libraries in a Macintosh Application. + * + * Copyright (c) 1993-1994 Lockheed Missle & Space Company, AI Center + * Copyright (c) 1995-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: tkMacOSXResource.r,v 1.2 2002/08/31 06:12:30 das Exp $ + */ + +/* + * We define SystemSevenOrLater so that our dialogs may use the + * auto center feature. + */ +#define SystemSevenOrLater 1 + +#include <Types.r> +#include <SysTypes.r> + +/* + * The folowing include and defines help construct + * the version string for Tcl. + */ + +#define RESOURCE_INCLUDED +#include "tcl.h" +#include "tk.h" + +#if (TK_RELEASE_LEVEL == 0) +# define RELEASE_LEVEL alpha +#elif (TK_RELEASE_LEVEL == 1) +# define RELEASE_LEVEL beta +#elif (TK_RELEASE_LEVEL == 2) +# define RELEASE_LEVEL final +#endif + +#if (TK_RELEASE_LEVEL == 2) +# define MINOR_VERSION (TK_MINOR_VERSION * 16) + TK_RELEASE_SERIAL +#else +# define MINOR_VERSION TK_MINOR_VERSION * 16 +#endif + +resource 'vers' (1) { + TK_MAJOR_VERSION, MINOR_VERSION, + RELEASE_LEVEL, 0x00, verUS, + TK_PATCH_LEVEL, + TK_PATCH_LEVEL ", by Ray Johnson & Jim Ingham " "\n" "© 1993-1997 Sun Microsystems" "\n" "© 1998-1999 Scriptics Inc." +}; + +resource 'vers' (2) { + TK_MAJOR_VERSION, MINOR_VERSION, + RELEASE_LEVEL, 0x00, verUS, + TK_PATCH_LEVEL, + "Wish " TK_PATCH_LEVEL " © 1993-1999" +}; + + +/* + * The mechanisim below loads Tcl source into the resource fork of the + * application. The example below creates a TEXT resource named + * "Init" from the file "init.tcl". This allows applications to use + * Tcl to define the behavior of the application without having to + * require some predetermined file structure - all needed Tcl "files" + * are located within the application. To source a file for the + * resource fork the source command has been modified to support + * sourcing from resources. In the below case "source -rsrc {Init}" + * will load the TEXT resource named "Init". + */ + +#include "tclMacTclCode.r" + +read 'TEXT' (10, "tk", purgeable, preload) "::library:tk.tcl"; +read 'TEXT' (11, "button", purgeable, preload) "::library:button.tcl"; +read 'TEXT' (12, "dialog", purgeable, preload) "::library:dialog.tcl"; +read 'TEXT' (13, "entry", purgeable, preload) "::library:entry.tcl"; +read 'TEXT' (14, "focus", purgeable, preload) "::library:focus.tcl"; +read 'TEXT' (15, "listbox", purgeable, preload) "::library:listbox.tcl"; +read 'TEXT' (16, "menu", purgeable, preload) "::library:menu.tcl"; +read 'TEXT' (17, "optionMenu", purgeable, preload) "::library:optMenu.tcl"; +read 'TEXT' (18, "palette", purgeable, preload) "::library:palette.tcl"; +read 'TEXT' (19, "scale", purgeable, preload) "::library:scale.tcl"; +read 'TEXT' (20, "scrollbar", purgeable, preload) "::library:scrlbar.tcl"; +read 'TEXT' (21, "tearoff", purgeable, preload) "::library:tearoff.tcl"; +read 'TEXT' (22, "text", purgeable, preload) "::library:text.tcl"; +read 'TEXT' (23, "tkerror", purgeable, preload) "::library:bgerror.tcl"; +read 'TEXT' (24, "Console", purgeable, preload) "::library:console.tcl"; +read 'TEXT' (25, "msgbox", purgeable, preload) "::library:msgbox.tcl"; +read 'TEXT' (26, "comdlg", purgeable, preload) "::library:comdlg.tcl"; + +/* + * The following resource is used when creating the 'env' variable in + * the Macintosh environment. The creation mechanisim looks for the + * 'STR#' resource named "Tcl Environment Variables" rather than a + * specific resource number. (In other words, feel free to change the + * resource id if it conflicts with your application.) Each string in + * the resource must be of the form "KEYWORD=SOME STRING". See Tcl + * documentation for futher information about the env variable. + */ + +/* A good example of something you may want to set is: + * "TCL_LIBRARY=My disk:etc." + */ + +resource 'STR#' (128, "Tcl Environment Variables") { + { "SCHEDULE_NAME=Agent Controller Schedule", + "SCHEDULE_PATH=Lozoya:System Folder:Tcl Lib:Tcl-Scheduler" + }; +}; + +/* + * 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 + * default dialog will not be shown and the Tcl procedure is expected to + * create and manage an About Dialog box. + */ + +resource 'DLOG' (128, "Default About Box", purgeable) { + {85, 107, 260, 412}, dBoxProc, visible, goAway, 0, + 128, "", centerMainScreen +}; + +resource 'DITL' (128, "About Box", purgeable) { + { + {143, 147, 167, 201}, Button {enabled, "Ok"}, + { 14, 108, 137, 314}, StaticText {disabled, + "Wish - Windowing Shell" "\n" "based on Tcl " + TCL_PATCH_LEVEL " & Tk " TK_PATCH_LEVEL "\n\n" + "Ray Johnson & Jim Ingham" "\n" + "Scriptics Inc." "\n" + "jim.ingham@cygnus.com"}, + { 19, 24, 119, 92}, Picture {enabled, 128} + } +}; + +data 'PICT' (128) { + $"13A4 0000 0000 0064 0044 0011 02FF 0C00" + $"FFFE 0000 0048 0000 0048 0000 0000 0000" + $"0064 0044 0000 0000 0001 000A 0000 0000" + $"0064 0044 0099 8044 0000 0000 0064 0044" + $"0000 0000 0000 0000 0048 0000 0048 0000" + $"0000 0008 0001 0008 0000 0000 0108 00D8" + $"0000 0000 0001 5A5A 8000 00FF 3736 FF00" + $"FF00 FF00 3535 FF00 FF00 CC00 3434 FF00" + $"FF00 9900 3333 FF00 FF00 6600 3736 FF00" + $"FF00 3300 3535 FF00 FF00 0000 3434 FF00" + $"CC00 FF00 3333 FF00 CC00 CC00 3736 FF00" + $"CC00 9900 3535 FF00 CC00 6600 FAFA FF00" + $"CC00 3300 3333 FF00 CC00 0000 3130 FF00" + $"9900 FF00 2F2F FF00 9900 CC00 FAFA FF00" + $"9900 9900 F9F9 FF00 9900 6600 3130 FF00" + $"9900 3300 2F2F FF00 9900 0000 2E2E FF00" + $"6600 FF00 F9F9 FF00 6600 CC00 3130 FF00" + $"6600 9900 2F2F FF00 6600 6600 2E2E FF00" + $"6600 3300 2D2D FF00 6600 0000 3130 FF00" + $"3300 FF00 2F2F FF00 3300 CC00 2E2E FF00" + $"3300 9900 2D2D FF00 3300 6600 3130 FF00" + $"3300 3300 2F2F FF00 3300 0000 2E2E FF00" + $"0000 FF00 2D2D FF00 0000 CC00 3130 FF00" + $"0000 9900 2F2F FF00 0000 6600 2E2E FF00" + $"0000 3300 2DF8 FF00 0000 0000 2B2A CC00" + $"FF00 FF00 2929 CC00 FF00 CC00 2828 CC00" + $"FF00 9900 27F8 CC00 FF00 6600 2B2A CC00" + $"FF00 3300 2929 CC00 FF00 0000 2828 CC00" + $"CC00 FF00 2727 CC00 CC00 CC00 2B2A CC00" + $"CC00 9900 2929 CC00 CC00 6600 2828 CC00" + $"CC00 3300 2727 CC00 CC00 0000 2B2A CC00" + $"9900 FF00 2929 CC00 9900 CC00 2828 CC00" + $"9900 9900 2727 CC00 9900 6600 DBDB CC00" + $"9900 3300 4747 CC00 9900 0000 4646 CC00" + $"6600 FF00 4545 CC00 6600 CC00 DBDB CC00" + $"6600 9900 4747 CC00 6600 6600 4646 CC00" + $"6600 3300 4545 CC00 6600 0000 DBDB CC00" + $"3300 FF00 4747 CC00 3300 CC00 4646 CC00" + $"3300 9900 4545 CC00 3300 6600 DBDB CC00" + $"3300 3300 4141 CC00 3300 0000 4040 CC00" + $"0000 FF00 3F3F CC00 0000 CC00 4342 CC00" + $"0000 9900 4141 CC00 0000 6600 4040 CC00" + $"0000 3300 3F3F CC00 0000 0000 4342 9900" + $"FF00 FF00 4141 9900 FF00 CC00 4040 9900" + $"FF00 9900 3F3F 9900 FF00 6600 4342 9900" + $"FF00 3300 4141 9900 FF00 0000 4040 9900" + $"CC00 FF00 3F3F 9900 CC00 CC00 4342 9900" + $"CC00 9900 4141 9900 CC00 6600 4040 9900" + $"CC00 3300 3F3F 9900 CC00 0000 4342 9900" + $"9900 FF00 4141 9900 9900 CC00 4040 9900" + $"9900 9900 3F3F 9900 9900 6600 3D3C 9900" + $"9900 3300 3B3B 9900 9900 0000 3A3A 9900" + $"6600 FF00 3939 9900 6600 CC00 3D3C 9900" + $"6600 9900 3B3B 9900 6600 6600 3A3A 9900" + $"6600 3300 3939 9900 6600 0000 3D3C 9900" + $"3300 FF00 3B3B 9900 3300 CC00 3A3A 9900" + $"3300 9900 3939 9900 3300 6600 3D3C 9900" + $"3300 3300 3B3B 9900 3300 0000 3A3A 9900" + $"0000 FF00 3939 9900 0000 CC00 3D3C 9900" + $"0000 9900 3B3B 9900 0000 6600 3A3A 9900" + $"0000 3300 3939 9900 0000 0000 3D3C 6600" + $"FF00 FF00 3B3B 6600 FF00 CC00 3A3A 6600" + $"FF00 9900 3939 6600 FF00 6600 3D3C 6600" + $"FF00 3300 3B3B 6600 FF00 0000 3A3A 6600" + $"CC00 FF00 3939 6600 CC00 CC00 3736 6600" + $"CC00 9900 3535 6600 CC00 6600 3434 6600" + $"CC00 3300 3333 6600 CC00 0000 3736 6600" + $"9900 FF00 3535 6600 9900 CC00 3434 6600" + $"9900 9900 3333 6600 9900 6600 3736 6600" + $"9900 3300 3535 6600 9900 0000 3434 6600" + $"6600 FF00 3333 6600 6600 CC00 3736 6600" + $"6600 9900 3535 6600 6600 6600 3434 6600" + $"6600 3300 3333 6600 6600 0000 3736 6600" + $"3300 FF00 3535 6600 3300 CC00 3434 6600" + $"3300 9900 3333 6600 3300 6600 3736 6600" + $"3300 3300 3535 6600 3300 0000 3434 6600" + $"0000 FF00 3333 6600 0000 CC00 3130 6600" + $"0000 9900 2F2F 6600 0000 6600 2E2E 6600" + $"0000 3300 F9F9 6600 0000 0000 3130 3300" + $"FF00 FF00 2F2F 3300 FF00 CC00 2E2E 3300" + $"FF00 9900 F9F9 3300 FF00 6600 3130 3300" + $"FF00 3300 2F2F 3300 FF00 0000 2E2E 3300" + $"CC00 FF00 2D2D 3300 CC00 CC00 3130 3300" + $"CC00 9900 2F2F 3300 CC00 6600 2E2E 3300" + $"CC00 3300 2D2D 3300 CC00 0000 3130 3300" + $"9900 FF00 2F2F 3300 9900 CC00 2E2E 3300" + $"9900 9900 2D2D 3300 9900 6600 3130 3300" + $"9900 3300 2F2F 3300 9900 0000 2E2E 3300" + $"6600 FF00 2DF8 3300 6600 CC00 2B2A 3300" + $"6600 9900 2929 3300 6600 6600 2828 3300" + $"6600 3300 27F8 3300 6600 0000 2B2A 3300" + $"3300 FF00 2929 3300 3300 CC00 2828 3300" + $"3300 9900 2727 3300 3300 6600 2B2A 3300" + $"3300 3300 2929 3300 3300 0000 2828 3300" + $"0000 FF00 2727 3300 0000 CC00 2B2A 3300" + $"0000 9900 2929 3300 0000 6600 2828 3300" + $"0000 3300 2727 3300 0000 0000 4948 0000" + $"FF00 FF00 4747 0000 FF00 CC00 4646 0000" + $"FF00 9900 4545 0000 FF00 6600 4948 0000" + $"FF00 3300 4747 0000 FF00 0000 4646 0000" + $"CC00 FF00 4545 0000 CC00 CC00 4948 0000" + $"CC00 9900 4747 0000 CC00 6600 4646 0000" + $"CC00 3300 4545 0000 CC00 0000 4342 0000" + $"9900 FF00 4141 0000 9900 CC00 4040 0000" + $"9900 9900 3F3F 0000 9900 6600 4342 0000" + $"9900 3300 4141 0000 9900 0000 4040 0000" + $"6600 FF00 3F3F 0000 6600 CC00 4342 0000" + $"6600 9900 4141 0000 6600 6600 4040 0000" + $"6600 3300 3F3F 0000 6600 0000 4342 0000" + $"3300 FF00 4141 0000 3300 CC00 4040 0000" + $"3300 9900 3F3F 0000 3300 6600 4342 0000" + $"3300 3300 4141 0000 3300 0000 4040 0000" + $"0000 FF00 3F3F 0000 0000 CC00 4342 0000" + $"0000 9900 4141 0000 0000 6600 4040 0000" + $"0000 3300 3F3F EE00 0000 0000 3D3C DD00" + $"0000 0000 3B3B BB00 0000 0000 3A3A AA00" + $"0000 0000 3939 8800 0000 0000 3D3C 7700" + $"0000 0000 3B3B 5500 0000 0000 3A3A 4400" + $"0000 0000 3939 2200 0000 0000 3D3C 1100" + $"0000 0000 3B3B 0000 EE00 0000 3A3A 0000" + $"DD00 0000 3939 0000 BB00 0000 3D3C 0000" + $"AA00 0000 3B3B 0000 8800 0000 3A3A 0000" + $"7700 0000 3939 0000 5500 0000 3D3C 0000" + $"4400 0000 3B3B 0000 2200 0000 3A3A 0000" + $"1100 0000 3939 0000 0000 EE00 3D3C 0000" + $"0000 DD00 3B3B 0000 0000 BB00 3A3A 0000" + $"0000 AA00 3939 0000 0000 8800 3D3C 0000" + $"0000 7700 3B3B 0000 0000 5500 3A3A 0000" + $"0000 4400 3939 0000 0000 2200 3736 0000" + $"0000 1100 3535 EE00 EE00 EE00 3434 DD00" + $"DD00 DD00 3333 BB00 BB00 BB00 3736 AA00" + $"AA00 AA00 3535 8800 8800 8800 3434 7700" + $"7700 7700 3333 5500 5500 5500 3736 4400" + $"4400 4400 3535 2200 2200 2200 3434 1100" + $"1100 1100 3333 0000 0000 0000 0000 0000" + $"0064 0044 0000 0000 0064 0044 0000 000A" + $"0000 0000 0064 0044 02BD 0013 E800 01F5" + $"F6FE 07FE 0E02 3232 33FD 3900 0EE6 001D" + $"FC00 01F5 F5FE 0700 08FE 0E02 3232 33FE" + $"3900 3AFC 40F2 4102 4033 07E9 0017 0100" + $"0EFC 40DC 4102 390E F5F5 0002 F5F5 F6FE" + $"0702 0E07 0016 0100 32D5 4104 4039 0E32" + $"33FD 3900 3AFC 40FC 4101 3200 0801 000E" + $"C141 010E 0008 0100 0EC1 4101 0800 0801" + $"000E C141 0107 0008 0100 0EC1 4101 0700" + $"0901 0007 C241 0240 F500 0E01 0007 E841" + $"0147 47DD 4102 4000 0012 0100 07F0 4100" + $"47FA 4101 3B3B DD41 0240 0000 1901 0007" + $"F141 0C47 3B0B 3B47 4141 4711 0505 3B47" + $"DF41 023A 0000 1701 00F6 F041 010B 0BFE" + $"4105 473B 0505 113B DE41 0239 0000 1A02" + $"00F5 40F3 410C 473B 053B 4741 4741 0B0B" + $"3B47 47DE 4102 3900 0018 0200 F540 F341" + $"0247 110B FE41 0447 1105 4147 DC41 0233" + $"0000 1B02 0000 40F3 4103 4711 1147 FE41" + $"0205 3547 F741 FD47 E941 0232 0000 1E02" + $"0000 40F2 4106 113B 4741 4735 0BF7 4106" + $"4741 390E 0E40 47EA 4102 0E00 0021 0200" + $"0040 F241 0711 3B47 4141 0B35 47F9 4102" + $"4740 07FE 0002 F640 47EB 4102 0E00 0023" + $"0200 0040 F341 0847 3541 4147 3B05 4147" + $"FA41 0947 3AF6 00F5 4F55 F50E 47EB 4102" + $"0700 0022 0200 003A F341 0147 3BFE 4101" + $"0B0B F941 0547 3AF5 0055 C8FE CE01 5640" + $"EB41 0207 0000 1F02 0000 39F0 4104 4741" + $"053B 47FB 4104 4740 F5F5 A4FC CE01 C85D" + $"EB41 02F6 0000 1F02 0000 39F0 4104 473B" + $"0541 47FC 4104 4740 07F6 C8FA CE00 64EC" + $"4103 40F5 0000 1C02 0000 39F0 4102 4711" + $"0BFA 4103 4708 2AC8 FACE 0164 D8EC 4100" + $"40FE 0025 0200 0039 EF41 020B 3B47 FC41" + $"0347 0FF5 A4FB CE02 C887 D8FC 41FE 47FC" + $"4100 47F9 4100 3AFE 0028 0200 0039 EF41" + $"020B 3B47 FD41 0347 3900 A4FA CE00 ABFA" + $"4109 3B11 3B41 4147 3B0B 3B47 FA41 0039" + $"FE00 2402 0000 33F1 4102 4741 0BFA 4101" + $"0779 F9CE 0064 FA41 0235 050B FD41 010B" + $"0BF9 4100 39FE 0028 0200 0032 F141 0247" + $"3B0B FC41 0247 39F6 F9CE 0187 D8FB 4103" + $"4741 050B FE41 0247 110B F941 0039 FE00" + $"2C02 0000 32F1 4102 473B 11FB 4101 0879" + $"FACE 05AA 4041 4147 47FE 410A 4741 0511" + $"4741 4147 3511 47FA 4100 32FE 002F 0200" + $"000E F141 0347 3B11 47FE 4103 4740 F6C8" + $"FACE 0564 D841 4039 39FE 4104 473B 053B" + $"47FE 4102 3541 47FA 4100 0EFE 0027 0200" + $"000E F141 0347 3B3B 47FE 4102 470F 79FA" + $"CE0C 8741 4032 F500 003A 4741 473B 05F2" + $"4100 0EFE 0027 0200 000E F141 0347 3B3B" + $"47FD 4101 0EA4 FACE 01AB AAFE C808 7900" + $"3947 4147 110B 47F3 4100 07FE 001C 0200" + $"000E EA41 0240 2BC8 F5CE 0881 0033 4741" + $"410B 3B47 F341 0007 FE00 1A02 0000 08EB" + $"4102 473A 55F4 CE06 5D00 3947 4741 0BF1" + $"4100 F6FE 001C 0200 0007 EB41 0247 3979" + $"F4CE 0739 0039 4747 3511 47F3 4101 40F5" + $"FE00 1C02 0000 07EB 4102 4739 A4F5 CE08" + $"AB0E 0040 4741 1141 47F3 4100 40FD 001B" + $"0200 0007 EB41 0247 39A4 F5CE 0787 0707" + $"4147 4111 47F2 4100 40FD 001B 0200 0007" + $"EB41 0247 39C8 F5CE 0763 F532 4747 3B3B" + $"47F2 4100 3AFD 001A 0300 00F6 40EC 4102" + $"4739 C8F5 CE05 39F5 4047 413B F041 0039" + $"FD00 1C03 0000 F540 EB41 0140 C8FD CE01" + $"C8A4 FCCE 03AB 080E 47ED 4100 39FD 001A" + $"FE00 0040 EB41 0040 FCCE 01A4 C8FC CE03" + $"FA07 4047 ED41 0032 FD00 1AFE 0000 40EA" + $"4100 AAFE CE02 87F9 C8FC CE02 560F 47EC" + $"4100 32FD 0019 FE00 0040 EA41 00AB FECE" + $"0264 56C8 FDCE 01C8 32EA 4100 0EFD 001B" + $"FE00 0040 ED41 030E 4047 87FE CE01 4055" + $"FCCE 01FA 40EA 4100 08FD 001A FE00 003A" + $"ED41 0807 0740 FBCE CEAB 3979 FDCE 00AB" + $"E841 0007 FD00 1CFE 0000 3AED 4108 0700" + $"F6A4 CECE 8733 79FD CE02 4147 47EA 4100" + $"07FD 001E FE00 0039 ED41 0807 2AA4 C8CE" + $"CE88 0E9D FECE 0364 1C39 39EB 4101 40F5" + $"FD00 1CFE 0000 39ED 4101 074F FDCE 0264" + $"F7A4 FECE 03AB 80F6 07EB 4100 40FC 001C" + $"FE00 0039 ED41 0108 79FE CE03 AB40 2BA4" + $"FCCE 02F7 0E47 EC41 0040 FC00 1CFE 0000" + $"39ED 4101 0879 FECE 03AB 40F6 C8FC CE02" + $"F615 47EC 4100 40FC 001E FE00 003A EE41" + $"0247 0E79 FECE 03AB 40F5 C8FD CE03 A4F5" + $"3A47 EC41 0040 FC00 1EFE 0000 3AEE 4102" + $"470E 56FE CE03 FB3A F6C8 FDCE 0280 F540" + $"EB41 0140 F5FD 001E FE00 0040 EE41 0947" + $"0F56 CECE C888 39F6 C8FD CE02 5601 40EB" + $"4101 40F5 FD00 1CFE 0000 40EE 4109 4739" + $"32CE CEC8 8839 2AC8 FDCE 0156 07E9 4100" + $"F6FD 001B FE00 0040 EE41 0847 3A32 CECE" + $"C864 152A FCCE 0132 07E9 4100 07FD 001A" + $"FE00 0040 ED41 0740 32AB CEC8 6439 4EFC" + $"CE01 3A07 E941 0007 FD00 1D03 0000 F540" + $"ED41 0740 0EAB CECE 640F 4EFD CE03 AB40" + $"0840 EA41 0007 FD00 1B03 0000 F540 EC41" + $"060F 81CE CE64 334E FDCE 02AB 400E E941" + $"000E FD00 1C02 0000 F6EC 4107 4715 FACE" + $"CE64 334E FDCE 0387 0F0E 47EA 4100 0EFD" + $"001C 0200 0007 EC41 0747 16F9 CEC8 6433" + $"4EFD CE03 6308 4047 EA41 000E FD00 1A02" + $"0000 07EB 4106 40F9 CEC8 6439 4EFD CE02" + $"3940 47E9 4100 32FD 001B 0200 0007 EA41" + $"0539 CECE 8839 F6FE CE04 AB41 4139 40EA" + $"4100 32FD 001C 0200 0007 EB41 0E47 3AC8" + $"CE88 39F6 C8CE CE64 15F6 F540 EA41 0033" + $"FD00 1A02 0000 07EA 410C 40A4 CE87 392A" + $"C8CE AB41 40F8 F6E9 4100 39FD 001B 0200" + $"000E EB41 0D47 41AB C887 39F5 C8CE ABAB" + $"CEA4 07E9 4100 39FD 001C 0200 000E ED41" + $"0947 3939 4787 C8AB 40F5 C8FD CE01 A40E" + $"E941 0039 FD00 1D02 0000 0EED 4109 473A" + $"0007 80CE AB40 F5C8 FDCE 0255 0E47 EA41" + $"0039 FD00 1B02 0000 0EEB 4107 0779 C8CE" + $"CE40 F6A4 FDCE 022B 3947 EA41 003A FD00" + $"1C02 0000 0EEC 4102 4739 79FE CE02 6407" + $"A4FE CE02 A407 40E9 4100 40FD 001A 0200" + $"0032 EA41 0632 A4CE CE88 0879 FECE 02F9" + $"0F47 E941 0040 FD00 1A02 0000 32EB 4107" + $"4740 F7C8 CE87 0E79 FECE 0132 40E8 4100" + $"40FD 0019 0200 0033 EA41 0B47 40F8 C8AB" + $"0E55 CECE 8015 47E8 4100 40FD 0017 0200" + $"0033 E941 0847 40F9 A439 4FCE CE5D E641" + $"0140 F5FE 0014 0200 0039 E841 0647 64FB" + $"392B C8AB E441 00F6 FE00 1102 0000 39E5" + $"4103 40F6 8764 E441 0007 FE00 1E02 0000" + $"39EB 4102 3A0E 0EFD 4102 0740 47F6 4104" + $"400F 0839 47F4 4100 07FE 0027 0200 0039" + $"FB41 0147 47F2 4102 0800 40FE 4102 0839" + $"47FC 4101 4747 FC41 0339 0039 47F4 4100" + $"07FE 0029 0200 0039 FB41 0140 39F3 4109" + $"470E F540 4141 470E 3347 FC41 0139 3AFD" + $"4104 4739 0039 47F4 4100 08FE 0036 0200" + $"003A FC41 0347 0E00 40FC 4102 4741 40FC" + $"4109 470E F540 4141 4733 0E47 FE41 0447" + $"4000 0E47 FE41 0447 3900 3941 FE40 F741" + $"000E FE00 3A02 0000 3AFD 410E 4740 0700" + $"0E40 4741 4147 390E 390E 40FE 4108 470E" + $"F540 4141 4739 0EFC 4103 0F00 0739 FE41" + $"0747 3900 3940 080F 39F7 4100 0EFE 0035" + $"0200 0040 FB41 020E 0040 FE41 0D47 4000" + $"3941 0032 4741 4147 0EF5 40FE 4101 4008" + $"FC41 023A 000E FD41 0547 3900 3939 33F5" + $"4100 0EFE 0039 0200 0040 FC41 0347 0E00" + $"40FE 4106 4732 0040 4139 40FE 4103 470E" + $"F540 FD41 0108 40FE 4104 4740 000E 47FE" + $"4106 4739 0007 F540 47F6 4100 32FE 003A" + $"0200 0040 FC41 0C47 0E00 4047 4141 470E" + $"0040 4747 FD41 0347 0EF5 40FE 410A 470E" + $"3947 4141 4740 000E 47FE 4107 4739 000E" + $"0007 4147 F741 0032 FE00 3802 0000 40FC" + $"4102 470E 00FD 4106 4739 003A 4740 39FE" + $"4102 470E F5FD 410A 4733 3347 4141 4740" + $"000E 47FE 4106 4739 0039 3900 0EF6 4100" + $"33FE 003A 0200 F540 FC41 0447 3200 0E39" + $"FD41 0B0E 0E40 333A 4741 413A 07F5 39FE" + $"4102 473A 0EFD 410F 40F5 0733 4041 4140" + $"0E00 0E40 0700 0E40 F841 0039 FE00 2902" + $"00F5 40FA 4101 3939 FB41 023A 3A40 FD41" + $"FD40 FD41 0240 0E40 FD41 0240 3940 FD41" + $"FA40 F741 0039 FE00 2A01 00F6 F941 0147" + $"47FB 4101 4747 FB41 0147 47FB 4101 3940" + $"FD41 0147 47FB 4100 47FE 4100 47F6 4100" + $"39FE 000D 0100 07E1 4100 40E4 4100 3AFE" + $"0009 0100 07C3 4100 3AFE 0009 0100 07C3" + $"4100 40FE 0009 0100 07C3 4100 40FE 0009" + $"0100 07C3 4100 40FE 000A 0100 0EC3 4103" + $"40F5 0000 0901 000E C241 02F6 0000 0901" + $"000E C241 0207 0000 0901 000E C241 0207" + $"0000 1101 000E ED41 FE40 003A F940 E241" + $"0207 0000 2B01 0032 F941 FE40 FE39 0632" + $"0E0E 0707 F6F5 F800 02F5 F5F6 FB07 FB0E" + $"0332 3233 33FB 3901 3A3A FB40 0207 0000" + $"0E0A 000E 3939 320E 0E07 07F6 F5C8 0002" + $"BD00 00FF" +}; + +/* + * Here is the custom file open dialog. This dialog is used instead of + * the default file dialog if the -filetypes flag is specified. + */ + +resource 'DLOG' (130, purgeable) { + {0, 0, 195, 344}, dBoxProc, invisible, noGoAway, 0, + 130, "", noAutoCenter +}; + +resource 'DITL' (130, "File Open Box", purgeable) { + { + {135, 252, 155, 332}, Button {enabled, "Open"}, + {104, 252, 124, 332}, Button {enabled, "Cancel"}, + { 0, 0, 0, 0}, HelpItem {disabled, HMScanhdlg {130}}, + { 8, 235, 24, 337}, UserItem {enabled}, + { 32, 252, 52, 332}, Button {enabled, "Eject"}, + { 60, 252, 80, 332}, Button {enabled, "Desktop"}, + { 29, 12, 159, 230}, UserItem {enabled}, + { 6, 12, 25, 230}, UserItem {enabled}, + { 91, 251, 92, 333}, Picture {disabled, 11}, + {168, 20, 187, 300}, Control {enabled, 131} + } +}; + +resource 'CNTL' (131, "File Types menu", purgeable) { + {168, 20, 187, 300}, + popupTitleLeftJust, + visible, + 80, + 132, + popupMenuCDEFProc, + 0, + "File Type:" +}; + + +resource 'MENU' (132, preload) { + 132, + textMenuProc, + 0xFFFF, enabled, "", {} +}; diff --git a/macosx/tkMacOSXScale.c b/macosx/tkMacOSXScale.c new file mode 100644 index 0000000..3c00610 --- /dev/null +++ b/macosx/tkMacOSXScale.c @@ -0,0 +1,431 @@ +/* + * tkMacOSXScale.c -- + * + * This file implements the Macintosh specific portion of the + * scale widget. + * + * Copyright (c) 1996 by Sun Microsystems, Inc. + * Copyright (c) 1998-2000 by Scriptics Corporation. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkMacOSXScale.c,v 1.2 2002/08/31 06:12:30 das Exp $ + */ + +#include "tkScale.h" +#include "tkInt.h" +#include <Carbon/Carbon.h> +#include "tkMacOSXInt.h" + +/* + * Defines used in this file. + */ +#define slider 1110 +#define inSlider 1 +#define inInc 2 +#define inDecr 3 + +/* + * Declaration of Macintosh specific scale structure. + */ + +typedef struct MacScale { + TkScale info; /* Generic scale info. */ + int flags; /* Flags. */ + ControlRef scaleHandle; /* Handle to the Scale control struct. */ +} MacScale; + +/* + * Globals uses locally in this file. + */ +static ControlActionUPP scaleActionProc = NULL; /* Pointer to func. */ + +/* + * Forward declarations for procedures defined later in this file: + */ + +static void MacScaleEventProc _ANSI_ARGS_((ClientData clientData, + XEvent *eventPtr)); +static pascal void ScaleActionProc _ANSI_ARGS_((ControlRef theControl, + ControlPartCode partCode)); + +/* + *---------------------------------------------------------------------- + * + * TkpCreateScale -- + * + * Allocate a new TkScale structure. + * + * Results: + * Returns a newly allocated TkScale structure. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TkScale * +TkpCreateScale(tkwin) + Tk_Window tkwin; +{ + MacScale *macScalePtr; + + macScalePtr = (MacScale *) ckalloc(sizeof(MacScale)); + macScalePtr->scaleHandle = NULL; + if (scaleActionProc == NULL) { + scaleActionProc = NewControlActionUPP(ScaleActionProc); + } + + Tk_CreateEventHandler(tkwin, ButtonPressMask, + MacScaleEventProc, (ClientData) macScalePtr); + + return (TkScale *) macScalePtr; +} + +/* + *---------------------------------------------------------------------- + * + * TkpDestroyScale -- + * + * Free Macintosh specific resources. + * + * Results: + * None + * + * Side effects: + * The slider control is destroyed. + * + *---------------------------------------------------------------------- + */ + +void +TkpDestroyScale(scalePtr) + TkScale *scalePtr; +{ + MacScale *macScalePtr = (MacScale *) scalePtr; + + /* + * Free Macintosh control. + */ + if (macScalePtr->scaleHandle != NULL) { + DisposeControl(macScalePtr->scaleHandle); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpDisplayScale -- + * + * This procedure is invoked as an idle handler to redisplay + * the contents of a scale widget. + * + * Results: + * None. + * + * Side effects: + * The scale gets redisplayed. + * + *---------------------------------------------------------------------- + */ + +void +TkpDisplayScale(clientData) + ClientData clientData; /* Widget record for scale. */ +{ + TkScale *scalePtr = (TkScale *) clientData; + Tk_Window tkwin = scalePtr->tkwin; + Tcl_Interp *interp = scalePtr->interp; + int result; + char string[PRINT_CHARS]; + MacScale *macScalePtr = (MacScale *) clientData; + Rect r; + WindowRef windowRef; + CGrafPtr destPort; + CGrafPtr saveWorld; + GDHandle saveDevice; + MacDrawable *macDraw; + SInt16 initialValue; + SInt16 minValue; + SInt16 maxValue; + SInt16 procID; + SInt32 controlReference; + Boolean initiallyVisible=true; + + fprintf(stderr,"TkpDisplayScale\n"); + scalePtr->flags &= ~REDRAW_PENDING; + if ((scalePtr->tkwin == NULL) || !Tk_IsMapped(scalePtr->tkwin)) { + goto done; + } + + /* + * Invoke the scale's command if needed. + */ + + Tcl_Preserve((ClientData) scalePtr); + if ((scalePtr->flags & INVOKE_COMMAND) && (scalePtr->command != NULL)) { + Tcl_Preserve((ClientData) interp); + sprintf(string, scalePtr->format, scalePtr->value); + result = Tcl_VarEval(interp, scalePtr->command, " ", string, + (char *) NULL); + if (result != TCL_OK) { + Tcl_AddErrorInfo(interp, "\n (command executed by scale)"); + Tcl_BackgroundError(interp); + } + Tcl_Release((ClientData) interp); + } + scalePtr->flags &= ~INVOKE_COMMAND; + if (scalePtr->flags & SCALE_DELETED) { + Tcl_Release((ClientData) scalePtr); + return; + } + Tcl_Release((ClientData) scalePtr); + + /* + * Now handle the part of redisplay that is the same for + * horizontal and vertical scales: border and traversal + * highlight. + */ + + if (scalePtr->highlightWidth != 0) { + GC gc; + + gc = Tk_GCForColor(scalePtr->highlightColorPtr, Tk_WindowId(tkwin)); + Tk_DrawFocusHighlight(tkwin, gc, scalePtr->highlightWidth, + Tk_WindowId(tkwin)); + } + Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin), scalePtr->bgBorder, + scalePtr->highlightWidth, scalePtr->highlightWidth, + Tk_Width(tkwin) - 2*scalePtr->highlightWidth, + Tk_Height(tkwin) - 2*scalePtr->highlightWidth, + scalePtr->borderWidth, scalePtr->relief); + + /* + * Set up port for drawing Macintosh control. + */ + macDraw = (MacDrawable *) Tk_WindowId(tkwin); + destPort=TkMacOSXGetDrawablePort(Tk_WindowId(tkwin)); + windowRef=GetWindowFromPort(destPort); + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin)); + + /* + * Create Macintosh control. + */ + if (macScalePtr->scaleHandle == NULL) { + fprintf(stderr,"Initialising scale\n"); + r.left=macDraw->xOff; + r.top=macDraw->yOff; + r.right=macDraw->xOff+Tk_Width(tkwin) - scalePtr->inset; + r.bottom=macDraw->yOff+Tk_Height(tkwin) - scalePtr->inset; + + initialValue=scalePtr->value; + minValue=scalePtr->toValue; + maxValue=scalePtr->fromValue; + procID=kControlSliderProc; + controlReference=(SInt32) macScalePtr; + macScalePtr->scaleHandle = NewControl(windowRef, + &r, "\p", initiallyVisible, initialValue,minValue,maxValue, + procID, controlReference); + + /* + * If we are foremost than make us active. + */ + if (windowRef==FrontWindow()) { + macScalePtr->flags |= ACTIVE; + } + } + + /* + * Finally draw the control. + */ + SetControlVisibility(macScalePtr->scaleHandle,true,true); + HiliteControl(macScalePtr->scaleHandle,0); + Draw1Control(macScalePtr->scaleHandle); + + SetGWorld(saveWorld, saveDevice); +done: + scalePtr->flags &= ~REDRAW_ALL; +} + +/* + *---------------------------------------------------------------------- + * + * TkpScaleElement -- + * + * Determine which part of a scale widget lies under a given + * point. + * + * Results: + * The return value is either TROUGH1, SLIDER, TROUGH2, or + * OTHER, depending on which of the scale's active elements + * (if any) is under the point at (x,y). + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkpScaleElement(scalePtr, x, y) + TkScale *scalePtr; /* Widget record for scale. */ + int x, y; /* Coordinates within scalePtr's window. */ +{ + MacScale *macScalePtr = (MacScale *) scalePtr; + ControlPartCode part; + Point where; + Rect bounds; + CGrafPtr saveWorld; + GDHandle saveDevice; + GWorldPtr destPort; + fprintf(stderr,"TkpScaleElement\n"); + + destPort = TkMacOSXGetDrawablePort(Tk_WindowId(scalePtr->tkwin)); + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + + /* + * All of the calculations in this procedure mirror those in + * DisplayScrollbar. Be sure to keep the two consistent. + */ + + TkMacOSXWinBounds((TkWindow *) scalePtr->tkwin, &bounds); + where.h = x + bounds.left; + where.v = y + bounds.top; + part = TestControl(macScalePtr->scaleHandle, where); + + SetGWorld(saveWorld, saveDevice); + + fprintf (stderr,"ScalePart %d, pos ( %d %d )\n", part, where.h, where.v ); + + switch (part) { + case inSlider: + return SLIDER; + case inInc: + if (scalePtr->orient == ORIENT_VERTICAL) { + return TROUGH1; + } else { + return TROUGH2; + } + case inDecr: + if (scalePtr->orient == ORIENT_VERTICAL) { + return TROUGH2; + } else { + return TROUGH1; + } + default: + return OTHER; + } +} + +/* + *-------------------------------------------------------------- + * + * MacScaleEventProc -- + * + * This procedure is invoked by the Tk dispatcher for + * ButtonPress events on scales. + * + * Results: + * None. + * + * Side effects: + * When the window gets deleted, internal structures get + * cleaned up. When it gets exposed, it is redisplayed. + * + *-------------------------------------------------------------- + */ + +static void +MacScaleEventProc(clientData, eventPtr) + ClientData clientData; /* Information about window. */ + XEvent *eventPtr; /* Information about event. */ +{ + MacScale *macScalePtr = (MacScale *) clientData; + Point where; + Rect bounds; + int part, x, y, dummy; + unsigned int state; + CGrafPtr saveWorld; + GDHandle saveDevice; + GWorldPtr destPort; + Window dummyWin; + + fprintf(stderr,"MacScaleEventProc\n" ); + /* + * To call Macintosh control routines we must have the port + * set to the window containing the control. We will then test + * which part of the control was hit and act accordingly. + */ + destPort = TkMacOSXGetDrawablePort(Tk_WindowId(macScalePtr->info.tkwin)); + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + TkMacOSXSetUpClippingRgn(Tk_WindowId(macScalePtr->info.tkwin)); + + TkMacOSXWinBounds((TkWindow *) macScalePtr->info.tkwin, &bounds); + where.h = eventPtr->xbutton.x + bounds.left; + where.v = eventPtr->xbutton.y + bounds.top; + fprintf(stderr,"calling TestControl\n"); + part = TestControl(macScalePtr->scaleHandle, where); + if (part == 0) { + return; + } + + part = TrackControl(macScalePtr->scaleHandle, where, scaleActionProc); + + /* + * Update the value for the widget. + */ + macScalePtr->info.value = GetControlValue(macScalePtr->scaleHandle); + /* TkScaleSetValue(&macScalePtr->info, macScalePtr->info.value, 1, 0); */ + + /* + * The TrackControl call will "eat" the ButtonUp event. We now + * generate a ButtonUp event so Tk will unset implicit grabs etc. + */ + GetMouse(&where); + XQueryPointer(NULL, None, &dummyWin, &dummyWin, &x, + &y, &dummy, &dummy, &state); + TkGenerateButtonEvent(x, y, Tk_WindowId(macScalePtr->info.tkwin), state); + + SetGWorld(saveWorld, saveDevice); +} + +/* + *-------------------------------------------------------------- + * + * ScaleActionProc -- + * + * Callback procedure used by the Macintosh toolbox call + * TrackControl. This call will update the display while + * the scrollbar is being manipulated by the user. + * + * Results: + * None. + * + * Side effects: + * May change the display. + * + *-------------------------------------------------------------- + */ + +static pascal void +ScaleActionProc(ControlRef theControl, ControlPartCode partCode) + /* ControlRef theControl; /* Handle to scrollbat control */ + /* ControlPartCode partCode; /* Part of scrollbar that was "hit" */ +{ + int value; + TkScale *scalePtr = (TkScale *) GetControlReference(theControl); + + fprintf(stderr,"ScaleActionProc\n"); + value = GetControlValue(theControl); + TkScaleSetValue(scalePtr, value, 1, 1); + Tcl_Preserve((ClientData) scalePtr); + Tcl_DoOneEvent(TCL_IDLE_EVENTS); + Tcl_Release((ClientData) scalePtr); +} + diff --git a/macosx/tkMacOSXScrlbr.c b/macosx/tkMacOSXScrlbr.c new file mode 100644 index 0000000..12b4443 --- /dev/null +++ b/macosx/tkMacOSXScrlbr.c @@ -0,0 +1,1076 @@ +/* + * tkMacOSXScrollbar.c -- + * + * This file implements the Macintosh specific portion of the scrollbar + * widget. The Macintosh scrollbar may also draw a windows grow + * region under certain cases. + * + * Copyright (c) 1996 by Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkMacOSXScrlbr.c,v 1.2 2002/08/31 06:12:30 das Exp $ + */ + +#include "tkScrollbar.h" +#include "tkMacOSXInt.h" + +#include <Carbon/Carbon.h> + +#include "tkMacOSXDebug.h" +/* + * The following definitions should really be in MacOS + * header files. They are included here as this is the only + * file that needs the declarations. + */ +typedef pascal void (*ThumbActionFunc)(void); + +typedef ThumbActionFunc ThumbActionUPP; + +enum { + uppThumbActionProcInfo = kPascalStackBased +}; + +#define NewThumbActionProc(userRoutine) ((ThumbActionUPP) (userRoutine)) + +/* + * Minimum slider length, in pixels (designed to make sure that the slider + * is always easy to grab with the mouse). + */ + +#define MIN_SLIDER_LENGTH 5 +#define MIN_SCROLLBAR_VALUE 0 +#define MAX_SCROLLBAR_VALUE 1000 +#define MAX_SCROLLBAR_DVALUE 1000.0 + +/* + * Declaration of Windows specific scrollbar structure. + */ + +typedef struct MacScrollbar { + TkScrollbar info; /* Generic scrollbar info */ + ControlRef sbHandle; /* Opaque handle to the Scrollbar contol struct */ + int macFlags; /* Various flags; see below */ +} MacScrollbar; + +/* Handle to the Scrollbar control structure */ + + +/* + * Flag bits for scrollbars on the Mac: + * + * ALREADY_DEAD: Non-zero means this scrollbar has been + * destroyed, but has not been cleaned up. + * IN_MODAL_LOOP: Non-zero means this scrollbar is in the middle + * of a modal loop. + * ACTIVE: Non-zero means this window is currently + * active (in the foreground). + * FLUSH_TOP: Flush with top of Mac window. + * FLUSH_BOTTOM: Flush with bottom of Mac window. + * FLUSH_RIGHT: Flush with right of Mac window. + * FLUSH_LEFT: Flush with left of Mac window. + * SCROLLBAR_GROW: Non-zero means this window draws the grow + * region for the toplevel window. + * AUTO_ADJUST: Non-zero means we automatically adjust + * the size of the widget to align correctly + * along a Mac window. + * DRAW_GROW: Non-zero means we draw the grow region. + */ + +#define ALREADY_DEAD 1 +#define IN_MODAL_LOOP 2 +#define ACTIVE 4 +#define FLUSH_TOP 8 +#define FLUSH_BOTTOM 16 +#define FLUSH_RIGHT 32 +#define FLUSH_LEFT 64 +#define SCROLLBAR_GROW 128 +#define AUTO_ADJUST 256 +#define DRAW_GROW 512 + +/* + * Globals uses locally in this file. + */ +static ControlActionUPP scrollActionProc = NULL; /* Pointer to func. */ +static ThumbActionUPP thumbActionProc = NULL; /* Pointer to func. */ +static TkScrollbar *activeScrollPtr = NULL; /* Non-null when in thumb */ + /* proc. */ +/* + * Forward declarations for procedures defined later in this file: + */ + +static pascal void ScrollbarActionProc _ANSI_ARGS_((ControlRef theControl, ControlPartCode partCode)); +static int ScrollbarBindProc _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, XEvent *eventPtr, + Tk_Window tkwin, KeySym keySym)); +static void ScrollbarEventProc _ANSI_ARGS_(( ClientData clientData, XEvent *eventPtr)); +static pascal void ThumbActionProc _ANSI_ARGS_((void)); +static void UpdateControlValues _ANSI_ARGS_((MacScrollbar *macScrollPtr)); + +/* + * The class procedure table for the scrollbar widget. Leave the proc fields + * initialized to NULL, which should happen automatically because of the scope + * at which the variable is declared. + */ + +Tk_ClassProcs tkpScrollbarProcs = { + sizeof(Tk_ClassProcs) /* size */ +}; + +/* + *---------------------------------------------------------------------- + * + * TkpCreateScrollbar -- + * + * Allocate a new TkScrollbar structure. + * + * Results: + * Returns a newly allocated TkScrollbar structure. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TkScrollbar * +TkpCreateScrollbar( + Tk_Window tkwin) /* New Tk Window. */ +{ + MacScrollbar * macScrollPtr; + TkWindow *winPtr = (TkWindow *)tkwin; + + if (scrollActionProc == NULL) { + scrollActionProc = NewControlActionUPP (ScrollbarActionProc); + thumbActionProc = NewThumbActionProc(ThumbActionProc); + } + + macScrollPtr = (MacScrollbar *) ckalloc(sizeof(MacScrollbar)); + macScrollPtr->sbHandle = NULL; + macScrollPtr->macFlags = 0; + + Tk_CreateEventHandler(tkwin, ActivateMask|ExposureMask| + StructureNotifyMask|FocusChangeMask, + ScrollbarEventProc, (ClientData) macScrollPtr); + + if (!Tcl_GetAssocData(winPtr->mainPtr->interp, "TkScrollbar", NULL)) { + Tcl_SetAssocData(winPtr->mainPtr->interp, "TkScrollbar", NULL, (ClientData)1); + TkCreateBindingProcedure(winPtr->mainPtr->interp, + winPtr->mainPtr->bindingTable, + (ClientData)Tk_GetUid("Scrollbar"), "<ButtonPress>", + ScrollbarBindProc, NULL, NULL); + } + return (TkScrollbar *) macScrollPtr; +} + +/* + *-------------------------------------------------------------- + * + * TkpDisplayScrollbar -- + * + * This procedure redraws the contents of a scrollbar window. + * It is invoked as a do-when-idle handler, so it only runs + * when there's nothing else for the application to do. + * + * Results: + * None. + * + * Side effects: + * Information appears on the screen. + * + *-------------------------------------------------------------- + */ + +void +TkpDisplayScrollbar( + ClientData clientData) /* Information about window. */ +{ + TkScrollbar *scrollPtr = (TkScrollbar *) clientData; + MacScrollbar *macScrollPtr = (MacScrollbar *) clientData; + Tk_Window tkwin = scrollPtr->tkwin; + + MacDrawable *macDraw; + CGrafPtr saveWorld; + GDHandle saveDevice; + GWorldPtr destPort; + WindowRef windowRef; + + if ((scrollPtr->tkwin == NULL) || !Tk_IsMapped(tkwin)) { + goto done; + } + + /* + * Draw the focus or any 3D relief we may have. + */ + if (scrollPtr->highlightWidth != 0) { + GC fgGC, bgGC; + + bgGC = Tk_GCForColor(scrollPtr->highlightBgColorPtr, + Tk_WindowId(tkwin)); + + if (scrollPtr->flags & GOT_FOCUS) { + fgGC = Tk_GCForColor(scrollPtr->highlightColorPtr, + Tk_WindowId(tkwin)); + TkpDrawHighlightBorder(tkwin, fgGC, bgGC, scrollPtr->highlightWidth, + Tk_WindowId(tkwin)); + } else { + TkpDrawHighlightBorder(tkwin, bgGC, bgGC, scrollPtr->highlightWidth, + Tk_WindowId(tkwin)); + } + } + Tk_Draw3DRectangle(tkwin, Tk_WindowId(tkwin), scrollPtr->bgBorder, + scrollPtr->highlightWidth, scrollPtr->highlightWidth, + Tk_Width(tkwin) - 2*scrollPtr->highlightWidth, + Tk_Height(tkwin) - 2*scrollPtr->highlightWidth, + scrollPtr->borderWidth, scrollPtr->relief); + + /* + * Set up port for drawing Macintosh control. + */ + macDraw = (MacDrawable *) Tk_WindowId(tkwin); + destPort = TkMacOSXGetDrawablePort(Tk_WindowId(tkwin)); + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + TkMacOSXSetUpClippingRgn(Tk_WindowId(tkwin)); + + if (macScrollPtr->sbHandle == NULL) { + Rect r; + SInt16 initialValue; + SInt16 minValue; + SInt16 maxValue; + SInt16 procID; + WindowRef frontNonFloating; + + r.left = r.top = 0; + r.right = r.bottom = 1; + + minValue = MIN_SCROLLBAR_VALUE; + maxValue = MAX_SCROLLBAR_VALUE; + initialValue = (minValue + maxValue)/2; + procID = kControlScrollBarLiveProc; + + windowRef = GetWindowFromPort(destPort); + macScrollPtr->sbHandle = NewControl(windowRef, &r, "\p", + false, initialValue,minValue,maxValue, + procID, (SInt32) scrollPtr); + + /* + * If we are foremost then make us active. + */ + + frontNonFloating = FrontNonFloatingWindow(); + + if ((windowRef == FrontWindow()) || TkpIsWindowFloating(windowRef)) { + macScrollPtr->macFlags |= ACTIVE; + } + } + + /* + * Update the control values before we draw. + */ + windowRef = GetControlOwner (macScrollPtr->sbHandle); + UpdateControlValues(macScrollPtr); + + if (macScrollPtr->macFlags & ACTIVE) { + Draw1Control(macScrollPtr->sbHandle); + if (macScrollPtr->macFlags & DRAW_GROW) { + DrawGrowIcon(windowRef); + } + } else { + HiliteControl (macScrollPtr->sbHandle, 255 ); + Draw1Control(macScrollPtr->sbHandle); + if (macScrollPtr->macFlags & DRAW_GROW) { + DrawGrowIcon(windowRef); + Tk_Fill3DRectangle(tkwin, Tk_WindowId(tkwin), scrollPtr->bgBorder, + Tk_Width(tkwin) - 13, Tk_Height(tkwin) - 13, + Tk_Width(tkwin), Tk_Height(tkwin), + 0, TK_RELIEF_FLAT); + } + } + + SetGWorld(saveWorld, saveDevice); + + done: + scrollPtr->flags &= ~REDRAW_PENDING; +} + +/* + *---------------------------------------------------------------------- + * + * TkpConfigureScrollbar -- + * + * This procedure is called after the generic code has finished + * processing configuration options, in order to configure + * platform specific options. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkpConfigureScrollbar(scrollPtr) + register TkScrollbar *scrollPtr; /* Information about widget; may or + * may not already have values for + * some fields. */ +{ +} + +/* + *---------------------------------------------------------------------- + * + * TkpComputeScrollbarGeometry -- + * + * After changes in a scrollbar's size or configuration, this + * procedure recomputes various geometry information used in + * displaying the scrollbar. + * + * Results: + * None. + * + * Side effects: + * The scrollbar will be displayed differently. + * + *---------------------------------------------------------------------- + */ + +void +TkpComputeScrollbarGeometry( + register TkScrollbar *scrollPtr) /* Scrollbar whose geometry may + * have changed. */ +{ + MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr; + int width, fieldLength, adjust = 0; + + if (scrollPtr->highlightWidth < 0) { + scrollPtr->highlightWidth = 0; + } + scrollPtr->inset = scrollPtr->highlightWidth + scrollPtr->borderWidth; + width = (scrollPtr->vertical) ? Tk_Width(scrollPtr->tkwin) + : Tk_Height(scrollPtr->tkwin); + scrollPtr->arrowLength = width - 2*scrollPtr->inset + 1; + fieldLength = (scrollPtr->vertical ? Tk_Height(scrollPtr->tkwin) + : Tk_Width(scrollPtr->tkwin)) + - 2*(scrollPtr->arrowLength + scrollPtr->inset); + if (fieldLength < 0) { + fieldLength = 0; + } + scrollPtr->sliderFirst = fieldLength*scrollPtr->firstFraction; + scrollPtr->sliderLast = fieldLength*scrollPtr->lastFraction; + + /* + * Adjust the slider so that some piece of it is always + * displayed in the scrollbar and so that it has at least + * a minimal width (so it can be grabbed with the mouse). + */ + + if (scrollPtr->sliderFirst > (fieldLength - 2*scrollPtr->borderWidth)) { + scrollPtr->sliderFirst = fieldLength - 2*scrollPtr->borderWidth; + } + if (scrollPtr->sliderFirst < 0) { + scrollPtr->sliderFirst = 0; + } + if (scrollPtr->sliderLast < (scrollPtr->sliderFirst + + MIN_SLIDER_LENGTH)) { + scrollPtr->sliderLast = scrollPtr->sliderFirst + MIN_SLIDER_LENGTH; + } + if (scrollPtr->sliderLast > fieldLength) { + scrollPtr->sliderLast = fieldLength; + } + scrollPtr->sliderFirst += scrollPtr->arrowLength + scrollPtr->inset; + scrollPtr->sliderLast += scrollPtr->arrowLength + scrollPtr->inset; + + /* + * Register the desired geometry for the window (leave enough space + * for the two arrows plus a minimum-size slider, plus border around + * the whole window, if any). Then arrange for the window to be + * redisplayed. + */ + + if (scrollPtr->vertical) { + if ((macScrollPtr->macFlags & AUTO_ADJUST) && + (macScrollPtr->macFlags & (FLUSH_RIGHT|FLUSH_LEFT))) { + adjust--; + } + Tk_GeometryRequest(scrollPtr->tkwin, + scrollPtr->width + 2*scrollPtr->inset + adjust, + 2*(scrollPtr->arrowLength + scrollPtr->borderWidth + + scrollPtr->inset)); + } else { + if ((macScrollPtr->macFlags & AUTO_ADJUST) && + (macScrollPtr->macFlags & (FLUSH_TOP|FLUSH_BOTTOM))) { + adjust--; + } + Tk_GeometryRequest(scrollPtr->tkwin, + 2*(scrollPtr->arrowLength + scrollPtr->borderWidth + + scrollPtr->inset), scrollPtr->width + 2*scrollPtr->inset + adjust); + } + Tk_SetInternalBorder(scrollPtr->tkwin, scrollPtr->inset); +} + +/* + *---------------------------------------------------------------------- + * + * TkpDestroyScrollbar -- + * + * Free data structures associated with the scrollbar control. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkpDestroyScrollbar( + TkScrollbar *scrollPtr) /* Scrollbar to destroy. */ +{ + MacScrollbar *macScrollPtr = (MacScrollbar *)scrollPtr; + + if (macScrollPtr->sbHandle != NULL) { + if (!(macScrollPtr->macFlags & IN_MODAL_LOOP)) { + DisposeControl(macScrollPtr->sbHandle); + macScrollPtr->sbHandle = NULL; + } + } + macScrollPtr->macFlags |= ALREADY_DEAD; +} + +/* + *-------------------------------------------------------------- + * + * TkpScrollbarPosition -- + * + * Determine the scrollbar element corresponding to a + * given position. + * + * Results: + * One of TOP_ARROW, TOP_GAP, etc., indicating which element + * of the scrollbar covers the position given by (x, y). If + * (x,y) is outside the scrollbar entirely, then OUTSIDE is + * returned. + * + * Side effects: + * None. + * + *-------------------------------------------------------------- + */ + +int +TkpScrollbarPosition( + TkScrollbar *scrollPtr, /* Scrollbar widget record. */ + int x, int y) /* Coordinates within scrollPtr's + * window. */ +{ + MacScrollbar *macScrollPtr = (MacScrollbar *) scrollPtr; + GWorldPtr destPort; + int length, width, tmp, inactive = false; + ControlPartCode part; + Point where; + Rect bounds; + int x0, y0; + + x0 = x; + y0 = y; + + if (scrollPtr->vertical) { + length = Tk_Height(scrollPtr->tkwin); + width = Tk_Width(scrollPtr->tkwin); + } else { + tmp = x; + x = y; + y = tmp; + length = Tk_Width(scrollPtr->tkwin); + width = Tk_Height(scrollPtr->tkwin); + } + + if ((x < scrollPtr->inset) || (x >= (width - scrollPtr->inset)) + || (y < scrollPtr->inset) || (y >= (length - scrollPtr->inset))) { + return OUTSIDE; + } + + /* + * All of the calculations in this procedure mirror those in + * DisplayScrollbar. Be sure to keep the two consistent. On the + * Macintosh we use the OS call TestControl to do this mapping. + * For TestControl to work, the scrollbar must be active and must + * be in the current port. + */ + + destPort = TkMacOSXGetDrawablePort(Tk_WindowId(scrollPtr->tkwin)); + SetGWorld(destPort, NULL); + UpdateControlValues(macScrollPtr); + if ( GetControlHilite(macScrollPtr->sbHandle) == 255 ) { + inactive = true; + HiliteControl(macScrollPtr->sbHandle, 0 ); + } + + TkMacOSXWinBounds((TkWindow *) scrollPtr->tkwin, &bounds); + where.h = x0 + bounds.left; + where.v = y0 + bounds.top; + part = TestControl(((MacScrollbar *) scrollPtr)->sbHandle, where); + if (inactive) { + HiliteControl(macScrollPtr->sbHandle, 255 ); + } + switch (part) { + case kControlUpButtonPart: + return TOP_ARROW; + case kControlPageUpPart: + return TOP_GAP; + case kControlIndicatorPart: + return SLIDER; + case kControlPageDownPart: + return BOTTOM_GAP; + case kControlDownButtonPart: + return BOTTOM_ARROW; + default: + return OUTSIDE; + } +} + +/* + *-------------------------------------------------------------- + * + * ThumbActionProc -- + * + * Callback procedure used by the Macintosh toolbox call + * TrackControl. This call is used to track the thumb of + * the scrollbar. Unlike the ScrollbarActionProc function + * this function is called once and basically takes over + * tracking the scrollbar from the control. This is done + * to avoid conflicts with what the control plans to draw. + * + * Results: + * None. + * + * Side effects: + * May change the display. + * + *-------------------------------------------------------------- + */ + +static pascal void +ThumbActionProc() +{ + register TkScrollbar *scrollPtr = activeScrollPtr; + register MacScrollbar *macScrollPtr = (MacScrollbar *) activeScrollPtr; + Tcl_DString cmdString; + int origValue, trackBarPin; + double thumbWidth, newFirstFraction, trackBarSize; + char valueString[40]; + Point currentPoint = { 0, 0 }; + Rect trackRect; + Tcl_Interp *interp; + MouseTrackingResult trackingResult; + OSErr err; + + if (scrollPtr == NULL) { + return; + } + + Tcl_DStringInit(&cmdString); + + /* + * First compute values that will remain constant during the tracking + * of the thumb. The variable trackBarSize is the length of the scrollbar + * minus the 2 arrows and half the width of the thumb on both sides + * (3 * arrowLength). The variable trackBarPin is the lower starting point + * of the drag region. + * + * Note: the arrowLength is equal to the thumb width of a Mac scrollbar. + */ + + origValue = GetControlValue(macScrollPtr->sbHandle); + GetControlBounds(macScrollPtr->sbHandle, &trackRect); + if (scrollPtr->vertical == true) { + trackBarSize = (double) (trackRect.bottom - trackRect.top + - (scrollPtr->arrowLength * 3)); + trackBarPin = trackRect.top + scrollPtr->arrowLength + + (scrollPtr->arrowLength / 2); + InsetRect(&trackRect, -25, -113); + + } else { + trackBarSize = (double) (trackRect.right - trackRect.left + - (scrollPtr->arrowLength * 3)); + trackBarPin = trackRect.left + scrollPtr->arrowLength + + (scrollPtr->arrowLength / 2); + InsetRect(&trackRect, -113, -25); + } + + /* + * Track the mouse while the button is held down. If the mouse is moved, + * we calculate the value that should be passed to the "command" part of + * the scrollbar. + */ + + do { + err = TrackMouseLocationWithOptions(NULL, + kTrackMouseLocationOptionDontConsumeMouseUp, + kEventDurationForever, + ¤tPoint, + NULL, + &trackingResult); + + if ((err==noErr) + && ((trackingResult == kMouseTrackingMouseDragged) + || (trackingResult == kMouseTrackingMouseMoved))) { + /* + * Calculating this value is a little tricky. We need to calculate a + * value for where the thumb would be in a Motif widget (variable + * thumb). This value is what the "command" expects and is what will + * be resent to the scrollbar to update its value. + */ + thumbWidth = scrollPtr->lastFraction - scrollPtr->firstFraction; + if (PtInRect(currentPoint, &trackRect)) { + if (scrollPtr->vertical == true) { + newFirstFraction = (1.0 - thumbWidth) * + ((double) (currentPoint.v - trackBarPin) / trackBarSize); + } else { + newFirstFraction = (1.0 - thumbWidth) * + ((double) (currentPoint.h - trackBarPin) / trackBarSize); + } + } else { + newFirstFraction = ((double) origValue / MAX_SCROLLBAR_DVALUE) + * (1.0 - thumbWidth); + } + sprintf(valueString, "%g", newFirstFraction); + Tcl_DStringSetLength(&cmdString, 0); + Tcl_DStringAppend(&cmdString, scrollPtr->command, + scrollPtr->commandSize); + Tcl_DStringAppendElement(&cmdString, "moveto"); + Tcl_DStringAppendElement(&cmdString, valueString); + interp = scrollPtr->interp; + Tcl_Preserve((ClientData) interp); + Tcl_GlobalEval(interp, cmdString.string); + Tcl_Release((ClientData) interp); + Tcl_DStringSetLength(&cmdString, 0); + Tcl_DStringAppend(&cmdString, "update idletasks", + strlen("update idletasks")); + Tcl_Preserve((ClientData) interp); + Tcl_GlobalEval(interp, cmdString.string); + Tcl_Release((ClientData) interp); + } + } while ((err==noErr) && trackingResult!=kMouseTrackingMouseReleased ); + + Tcl_DStringFree(&cmdString); + return; +} + +/* + *-------------------------------------------------------------- + * + * ScrollbarActionProc -- + * + * Callback procedure used by the Macintosh toolbox call + * TrackControl. This call will update the display while + * the scrollbar is being manipulated by the user. + * + * Results: + * None. + * + * Side effects: + * May change the display. + * + *-------------------------------------------------------------- + */ + +static pascal void +ScrollbarActionProc( + ControlRef theControl, /* Handle to scrollbat control */ + ControlPartCode partCode) /* Part of scrollbar that was "hit" */ +{ + TkScrollbar *scrollPtr = (TkScrollbar *) GetControlReference(theControl); + Tcl_DString cmdString; + + Tcl_DStringInit(&cmdString); + Tcl_DStringAppend(&cmdString, scrollPtr->command, + scrollPtr->commandSize); + + if ( partCode == kControlUpButtonPart || + partCode == kControlDownButtonPart ) { + Tcl_DStringAppendElement(&cmdString, "scroll"); + Tcl_DStringAppendElement(&cmdString, + (partCode == kControlUpButtonPart ) ? "-1" : "1"); + Tcl_DStringAppendElement(&cmdString, "unit"); + } else if (partCode == kControlPageUpPart || partCode == kControlPageDownPart ) { + Tcl_DStringAppendElement(&cmdString, "scroll"); + Tcl_DStringAppendElement(&cmdString, + (partCode == kControlPageUpPart ) ? "-1" : "1"); + Tcl_DStringAppendElement(&cmdString, "page"); + } + Tcl_Preserve((ClientData) scrollPtr->interp); + Tcl_DStringAppend(&cmdString, "; update idletasks", + strlen("; update idletasks")); + Tcl_GlobalEval(scrollPtr->interp, cmdString.string); + Tcl_Release((ClientData) scrollPtr->interp); + + Tcl_DStringFree(&cmdString); +} + +/* + *-------------------------------------------------------------- + * + * ScrollbarBindProc -- + * + * This procedure is invoked when the default <ButtonPress> + * binding on the Scrollbar bind tag fires. + * + * Results: + * None. + * + * Side effects: + * The event enters a modal loop. + * + *-------------------------------------------------------------- + */ + +static int +ScrollbarBindProc( + ClientData clientData, /* Not used. */ + Tcl_Interp *interp, /* Interp with binding. */ + XEvent *eventPtr, /* X event that triggered binding. */ + Tk_Window tkwin, /* Target window for event. */ + KeySym keySym) /* The KeySym if a key event. */ +{ + TkWindow *winPtr = (TkWindow*)tkwin; + TkScrollbar *scrollPtr = (TkScrollbar *) winPtr->instanceData; + MacScrollbar *macScrollPtr = (MacScrollbar *) winPtr->instanceData; + + Tcl_Preserve((ClientData)scrollPtr); + macScrollPtr->macFlags |= IN_MODAL_LOOP; + + if (eventPtr->type == ButtonPress) { + Point where; + Rect bounds; + int part, x, y, dummy; + unsigned int state; + CGrafPtr saveWorld; + GDHandle saveDevice; + GWorldPtr destPort; + Window window; + + /* + * To call Macintosh control routines we must have the port + * set to the window containing the control. We will then test + * which part of the control was hit and act accordingly. + */ + destPort = TkMacOSXGetDrawablePort(Tk_WindowId(scrollPtr->tkwin)); + GetGWorld(&saveWorld, &saveDevice); + SetGWorld(destPort, NULL); + TkMacOSXSetUpClippingRgn(Tk_WindowId(scrollPtr->tkwin)); + + TkMacOSXWinBounds((TkWindow *) scrollPtr->tkwin, &bounds); + where.h = eventPtr->xbutton.x + bounds.left; + where.v = eventPtr->xbutton.y + bounds.top; + part = TestControl(macScrollPtr->sbHandle, where); + if (part == kControlIndicatorPart && scrollPtr->jump == false) { + /* + * Case 1: In thumb, no jump scrolling. Call track control + * with the thumb action proc which will do most of the work. + * Set the global activeScrollPtr to the current control + * so the callback may have access to it. + */ + activeScrollPtr = scrollPtr; + part = TrackControl(macScrollPtr->sbHandle, where, + (ControlActionUPP) thumbActionProc); + activeScrollPtr = NULL; + } else if (part == kControlIndicatorPart) { + /* + * Case 2: in thumb with jump scrolling. Call TrackControl + * with a NULL action proc. Use the new value of the control + * to set update the control. + */ + part = TrackControl(macScrollPtr->sbHandle, where, NULL); + if (part == kControlIndicatorPart) { + double newFirstFraction, thumbWidth; + Tcl_DString cmdString; + char valueString[TCL_DOUBLE_SPACE]; + + /* + * The following calculation takes the new control + * value and maps it to what Tk needs for its variable + * thumb size representation. + */ + thumbWidth = scrollPtr->lastFraction + - scrollPtr->firstFraction; + newFirstFraction = (1.0 - thumbWidth) * + ((double) GetControlValue(macScrollPtr->sbHandle) / MAX_SCROLLBAR_DVALUE); + sprintf(valueString, "%g", newFirstFraction); + + Tcl_DStringInit(&cmdString); + Tcl_DStringAppend(&cmdString, scrollPtr->command, + strlen(scrollPtr->command)); + Tcl_DStringAppendElement(&cmdString, "moveto"); + Tcl_DStringAppendElement(&cmdString, valueString); + Tcl_DStringAppend(&cmdString, "; update idletasks", + strlen("; update idletasks")); + + interp = scrollPtr->interp; + Tcl_Preserve((ClientData) interp); + Tcl_GlobalEval(interp, cmdString.string); + Tcl_Release((ClientData) interp); + Tcl_DStringFree(&cmdString); + } + } else if (part != 0) { + /* + * Case 3: in any other part of the scrollbar. We call + * TrackControl with the scrollActionProc which will do + * most all the work. + */ + TrackControl(macScrollPtr->sbHandle, where, scrollActionProc); + HiliteControl(macScrollPtr->sbHandle, 0); + } + + /* + * The TrackControl call will "eat" the ButtonUp event. We now + * generate a ButtonUp event so Tk will unset implicit grabs etc. + */ + GetMouse(&where); + XQueryPointer(NULL, None, &window, &window, &x, + &y, &dummy, &dummy, &state); + window = Tk_WindowId(scrollPtr->tkwin); + TkGenerateButtonEvent(x, y, window, state); + + SetGWorld(saveWorld, saveDevice); + } + + if (macScrollPtr->sbHandle && (macScrollPtr->macFlags & ALREADY_DEAD)) { + DisposeControl(macScrollPtr->sbHandle); + macScrollPtr->sbHandle = NULL; + } + macScrollPtr->macFlags &= ~IN_MODAL_LOOP; + Tcl_Release((ClientData)scrollPtr); + + return TCL_OK; +} + +/* + *-------------------------------------------------------------- + * + * ScrollbarEventProc -- + * + * This procedure is invoked by the Tk dispatcher for various + * events on scrollbars. + * + * Results: + * None. + * + * Side effects: + * When the window gets deleted, internal structures get + * cleaned up. When it gets exposed, it is redisplayed. + * + *-------------------------------------------------------------- + */ + +static void +ScrollbarEventProc( + ClientData clientData, /* Information about window. */ + XEvent *eventPtr) /* Information about event. */ +{ + TkScrollbar *scrollPtr = (TkScrollbar *) clientData; + MacScrollbar *macScrollPtr = (MacScrollbar *) clientData; + + if (eventPtr->type == UnmapNotify) { + TkMacOSXSetScrollbarGrow((TkWindow *) scrollPtr->tkwin, false); + } else if (eventPtr->type == ActivateNotify) { + macScrollPtr->macFlags |= ACTIVE; + TkScrollbarEventuallyRedraw((ClientData) scrollPtr); + } else if (eventPtr->type == DeactivateNotify) { + macScrollPtr->macFlags &= ~ACTIVE; + TkScrollbarEventuallyRedraw((ClientData) scrollPtr); + } else { + TkScrollbarEventProc(clientData, eventPtr); + } +} + +/* + *-------------------------------------------------------------- + * + * UpdateControlValues -- + * + * This procedure updates the Macintosh scrollbar control + * to display the values defined by the Tk scrollbar. + * + * Results: + * None. + * + * Side effects: + * The Macintosh control is updated. + * + *-------------------------------------------------------------- + */ + +static void +UpdateControlValues( + MacScrollbar *macScrollPtr) /* Scrollbar data struct. */ +{ + TkScrollbar *scrollPtr = (TkScrollbar *) macScrollPtr; + Tk_Window tkwin = scrollPtr->tkwin; + MacDrawable * macDraw = (MacDrawable *) Tk_WindowId(scrollPtr->tkwin); + WindowRef windowRef = GetControlOwner(macScrollPtr->sbHandle); + double middle; + SInt32 viewSize; + int flushRight = false; + int flushBottom = false; + Rect contrlRect, portRect; + UInt8 contrlHilite; + + /* + * We can't use the Macintosh commands SizeControl and MoveControl as these + * calls will also cause a redraw which in our case will also cause + * flicker. To avoid this we adjust the control record directly. The + * Draw1Control command appears to just draw where ever the control says to + * draw so this seems right. + * + * NOTE: changing the control record directly may not work when + * Apple releases the Copland version of the MacOS (or when hell is cold). + */ + + contrlRect.left = macDraw->xOff + scrollPtr->inset; + contrlRect.top = macDraw->yOff + scrollPtr->inset; + contrlRect.right = macDraw->xOff + Tk_Width(tkwin) - scrollPtr->inset; + contrlRect.bottom = macDraw->yOff + Tk_Height(tkwin) - scrollPtr->inset; + + SetControlBounds(macScrollPtr->sbHandle, &contrlRect ); + + /* + * To make Tk applications look more like Macintosh applications without + * requiring additional work by the Tk developer we do some cute tricks. + * The first trick plays with the size of the widget to get it to overlap + * with the side of the window by one pixel (we don't do this if the placer + * is the geometry manager). The second trick shrinks the scrollbar if it + * it covers the area of the grow region ao the scrollbar can also draw + * the grow region if need be. + */ + if (!strcmp(macDraw->winPtr->geomMgrPtr->name, "place")) { + macScrollPtr->macFlags &= AUTO_ADJUST; + } else { + macScrollPtr->macFlags |= AUTO_ADJUST; + } + GetPortBounds ( GetWindowPort ( windowRef ), &portRect ); + if ( portRect.left == contrlRect.left ) { + if (macScrollPtr->macFlags & AUTO_ADJUST) { + contrlRect.left--; + SetControlBounds ( macScrollPtr->sbHandle, &contrlRect ); + } + if (!(macScrollPtr->macFlags & FLUSH_LEFT)) { + macScrollPtr->macFlags |= FLUSH_LEFT; + if (scrollPtr->vertical) { + TkpComputeScrollbarGeometry(scrollPtr); + } + } + } else if (macScrollPtr->macFlags & FLUSH_LEFT) { + macScrollPtr->macFlags &= ~FLUSH_LEFT; + if (scrollPtr->vertical) { + TkpComputeScrollbarGeometry(scrollPtr); + } + } + + if (portRect.top == contrlRect.top) { + if (macScrollPtr->macFlags & AUTO_ADJUST) { + contrlRect.top--; + } + if (!(macScrollPtr->macFlags & FLUSH_TOP)) { + macScrollPtr->macFlags |= FLUSH_TOP; + if (! scrollPtr->vertical) { + TkpComputeScrollbarGeometry(scrollPtr); + } + } + } else if (macScrollPtr->macFlags & FLUSH_TOP) { + macScrollPtr->macFlags &= ~FLUSH_TOP; + if (! scrollPtr->vertical) { + TkpComputeScrollbarGeometry(scrollPtr); + } + } + + if (portRect.right == contrlRect.right) { + flushRight = true; + if (macScrollPtr->macFlags & AUTO_ADJUST) { + contrlRect.right++; + } + if (!(macScrollPtr->macFlags & FLUSH_RIGHT)) { + macScrollPtr->macFlags |= FLUSH_RIGHT; + if (scrollPtr->vertical) { + TkpComputeScrollbarGeometry(scrollPtr); + } + } + } else if (macScrollPtr->macFlags & FLUSH_RIGHT) { + macScrollPtr->macFlags &= ~FLUSH_RIGHT; + if (scrollPtr->vertical) { + TkpComputeScrollbarGeometry(scrollPtr); + } + } + + if (portRect.bottom == contrlRect.bottom) { + flushBottom = true; + if (macScrollPtr->macFlags & AUTO_ADJUST) { + contrlRect.bottom++; + } + if (!(macScrollPtr->macFlags & FLUSH_BOTTOM)) { + macScrollPtr->macFlags |= FLUSH_BOTTOM; + if (! scrollPtr->vertical) { + TkpComputeScrollbarGeometry(scrollPtr); + } + } + } else if (macScrollPtr->macFlags & FLUSH_BOTTOM) { + macScrollPtr->macFlags &= ~FLUSH_BOTTOM; + if (! scrollPtr->vertical) { + TkpComputeScrollbarGeometry(scrollPtr); + } + } + + /* + * If the scrollbar is flush against the bottom right hand corner then + * it may need to draw the grow region for the window so we let the + * wm code know about this scrollbar. We don't actually draw the grow + * region, however, unless we are currently resizable. + */ + macScrollPtr->macFlags &= ~DRAW_GROW; + if (flushBottom && flushRight) { + TkMacOSXSetScrollbarGrow((TkWindow *) tkwin, true); + if (TkMacOSXResizable(macDraw->toplevel->winPtr)) { + if (scrollPtr->vertical) { + contrlRect.bottom -= 14; + } else { + contrlRect.right -= 14; + } + macScrollPtr->macFlags |= DRAW_GROW; + } + } else { + TkMacOSXSetScrollbarGrow((TkWindow *) tkwin, false); + } + + /* + * Given the Tk parameters for the fractions of the start and + * end of the thumb, the following calculation determines the + * location for the fixed sized Macintosh thumb. + */ + middle = scrollPtr->firstFraction / (scrollPtr->firstFraction + + (1.0 - scrollPtr->lastFraction)); + viewSize = (SInt32)((scrollPtr->lastFraction-scrollPtr->firstFraction) + * MAX_SCROLLBAR_DVALUE); + SetControlViewSize(macScrollPtr->sbHandle,viewSize); + SetControlValue(macScrollPtr->sbHandle, + (short) (middle * MAX_SCROLLBAR_VALUE) ); + contrlHilite=GetControlHilite(macScrollPtr->sbHandle); + if ( contrlHilite == 0 || contrlHilite == 255) { + if (scrollPtr->firstFraction == 0.0 && + scrollPtr->lastFraction == 1.0) { + HiliteControl(macScrollPtr->sbHandle,255); + } else { + HiliteControl(macScrollPtr->sbHandle,0); + } + } + if ( !IsControlVisible (macScrollPtr -> sbHandle) ) { + SetControlVisibility(macScrollPtr->sbHandle,TRUE,FALSE); + } +} diff --git a/macosx/tkMacOSXSend.c b/macosx/tkMacOSXSend.c new file mode 100644 index 0000000..1647f75 --- /dev/null +++ b/macosx/tkMacOSXSend.c @@ -0,0 +1,552 @@ +/* + * tkMacOSXSend.c -- + * + * This file provides procedures that implement the "send" + * command, allowing commands to be passed from interpreter + * to interpreter. This current implementation for the Mac + * has most functionality stubed out. + * + * The current plan, which we have not had time to implement, is + * for the first Wish app to create a gestalt of type 'WIsH'. + * This gestalt will point to a table, in system memory, of + * Tk apps. Each Tk app, when it starts up, will register their + * name, and process ID, in this table. This will allow us to + * implement "tk appname". + * + * Then the send command will look up the process id of the target + * app in this table, and send an AppleEvent to that process. The + * AppleEvent handler is much like the do script handler, except that + * you have to specify the name of the tk app as well, since there may + * be many interps in one wish app, and you need to send it to the + * right one. + * + * Implementing this has been on our list of things to do, but what + * with the demise of Tcl at Sun, and the lack of resources at + * Scriptics it may not get done for awhile. So this sketch is + * offered for the brave to attempt if they need the functionality... + * + * Copyright (c) 1989-1994 The Regents of the University of California. + * Copyright (c) 1994-1998 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkMacOSXSend.c,v 1.2 2002/08/31 06:12:30 das Exp $ + */ + +#include <Carbon/Carbon.h> +/* +#include <Gestalt.h> +*/ +#include "tkPort.h" +#include "tkInt.h" + +EXTERN int Tk_SendObjCmd _ANSI_ARGS_((ClientData clientData, + Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[])); + + /* + * The following structure is used to keep track of the + * interpreters registered by this process. + */ + +typedef struct RegisteredInterp { + char *name; /* Interpreter's name (malloc-ed). */ + Tcl_Interp *interp; /* Interpreter associated with + * name. */ + struct RegisteredInterp *nextPtr; + /* Next in list of names associated + * with interps in this process. + * NULL means end of list. */ +} RegisteredInterp; + +/* + * A registry of all interpreters for a display is kept in a + * property "InterpRegistry" on the root window of the display. + * It is organized as a series of zero or more concatenated strings + * (in no particular order), each of the form + * window space name '\0' + * where "window" is the hex id of the comm. window to use to talk + * to an interpreter named "name". + * + * When the registry is being manipulated by an application (e.g. to + * add or remove an entry), it is loaded into memory using a structure + * of the following type: + */ + +typedef struct NameRegistry { + TkDisplay *dispPtr; /* Display from which the registry was + * read. */ + int locked; /* Non-zero means that the display was + * locked when the property was read in. */ + int modified; /* Non-zero means that the property has + * been modified, so it needs to be written + * out when the NameRegistry is closed. */ + unsigned long propLength; /* Length of the property, in bytes. */ + char *property; /* The contents of the property, or NULL + * if none. See format description above; + * this is *not* terminated by the first + * null character. Dynamically allocated. */ + int allocedByX; /* Non-zero means must free property with + * XFree; zero means use ckfree. */ +} NameRegistry; + +static int initialized = false; /* A flag to denote if we have initialized yet. */ + +static RegisteredInterp *interpListPtr = NULL; +/* List of all interpreters + * registered by this process. */ + + /* + * The information below is used for communication between processes + * during "send" commands. Each process keeps a private window, never + * even mapped, with one property, "Comm". When a command is sent to + * an interpreter, the command is appended to the comm property of the + * communication window associated with the interp's process. Similarly, + * when a result is returned from a sent command, it is also appended + * to the comm property. + * + * Each command and each result takes the form of ASCII text. For a + * command, the text consists of a zero character followed by several + * null-terminated ASCII strings. The first string consists of the + * single letter "c". Subsequent strings have the form "option value" + * where the following options are supported: + * + * -r commWindow serial + * + * This option means that a response should be sent to the window + * whose X identifier is "commWindow" (in hex), and the response should + * be identified with the serial number given by "serial" (in decimal). + * If this option isn't specified then the send is asynchronous and + * no response is sent. + * + * -n name + * "Name" gives the name of the application for which the command is + * intended. This option must be present. + * + * -s script + * + * "Script" is the script to be executed. This option must be present. + * + * The options may appear in any order. The -n and -s options must be + * present, but -r may be omitted for asynchronous RPCs. For compatibility + * with future releases that may add new features, there may be additional + * options present; as long as they start with a "-" character, they will + * be ignored. + * + * A result also consists of a zero character followed by several null- + * terminated ASCII strings. The first string consists of the single + * letter "r". Subsequent strings have the form "option value" where + * the following options are supported: + * + * -s serial + * + * Identifies the command for which this is the result. It is the + * same as the "serial" field from the -s option in the command. This + * option must be present. + * + * -c code + * + * "Code" is the completion code for the script, in decimal. If the + * code is omitted it defaults to TCL_OK. + * + * -r result + * + * "Result" is the result string for the script, which may be either + * a result or an error message. If this field is omitted then it + * defaults to an empty string. + * + * -i errorInfo + * + * "ErrorInfo" gives a string with which to initialize the errorInfo + * variable. This option may be omitted; it is ignored unless the + * completion code is TCL_ERROR. + * + * -e errorCode + * + * "ErrorCode" gives a string with with to initialize the errorCode + * variable. This option may be omitted; it is ignored unless the + * completion code is TCL_ERROR. + * + * Options may appear in any order, and only the -s option must be + * present. As with commands, there may be additional options besides + * these; unknown options are ignored. + */ + + /* + * The following variable is the serial number that was used in the + * last "send" command. It is exported only for testing purposes. + */ + +int tkSendSerial = 0; + + /* + * Maximum size property that can be read at one time by + * this module: + */ + +#define MAX_PROP_WORDS 100000 + +/* + * Forward declarations for procedures defined later in this file: + */ + +static int SendInit _ANSI_ARGS_((Tcl_Interp *interp)); +/* +static int AppendErrorProc _ANSI_ARGS_((ClientData clientData, + XErrorEvent *errorPtr)); +static void DeleteProc _ANSI_ARGS_((ClientData clientData)); +static void RegAddName _ANSI_ARGS_((NameRegistry *regPtr, + char *name, Window commWindow)); +static void RegClose _ANSI_ARGS_((NameRegistry *regPtr)); +static void RegDeleteName _ANSI_ARGS_((NameRegistry *regPtr, + char *name)); +static Window RegFindName _ANSI_ARGS_((NameRegistry *regPtr, + char *name)); +static NameRegistry * RegOpen _ANSI_ARGS_((Tcl_Interp *interp, + TkWindow *winPtr, int lock)); +static void SendEventProc _ANSI_ARGS_((ClientData clientData, + XEvent *eventPtr)); +static Bool SendRestrictProc _ANSI_ARGS_((Display *display, + XEvent *eventPtr, char *arg)); +static int ServerSecure _ANSI_ARGS_((TkDisplay *dispPtr)); +static void TimeoutProc _ANSI_ARGS_((ClientData clientData)); +static int ValidateName _ANSI_ARGS_((TkDisplay *dispPtr, + char *name, Window commWindow, int oldOK)); +*/ + +/* + *-------------------------------------------------------------- + * + * Tk_SetAppName -- + * + * This procedure is called to associate an ASCII name with a Tk + * application. If the application has already been named, the + * name replaces the old one. + * + * Results: + * The return value is the name actually given to the application. + * This will normally be the same as name, but if name was already + * in use for an application then a name of the form "name #2" will + * be chosen, with a high enough number to make the name unique. + * + * Side effects: + * Registration info is saved, thereby allowing the "send" command + * to be used later to invoke commands in the application. In + * addition, the "send" command is created in the application's + * interpreter. The registration will be removed automatically + * if the interpreter is deleted or the "send" command is removed. + * + *-------------------------------------------------------------- + */ + +CONST char * +Tk_SetAppName( + Tk_Window tkwin, /* Token for any window in the application + * to be named: it is just used to identify + * the application and the display. */ + CONST char *name) /* The name that will be used to + * refer to the interpreter in later + * "send" commands. Must be globally + * unique. */ +{ + TkWindow *winPtr = (TkWindow *) tkwin; + Tcl_Interp *interp = winPtr->mainPtr->interp; + int i, suffix, offset, result; + RegisteredInterp *riPtr, *prevPtr; + CONST char *actualName; + Tcl_DString dString; + Tcl_Obj *resultObjPtr, *interpNamePtr; + char *interpName; + + if (!initialized) { + SendInit(interp); + } + + /* + * See if the application is already registered; if so, remove its + * current name from the registry. The deletion of the command + * will take care of disposing of this entry. + */ + + for (riPtr = interpListPtr, prevPtr = NULL; riPtr != NULL; + prevPtr = riPtr, riPtr = riPtr->nextPtr) { + if (riPtr->interp == interp) { + if (prevPtr == NULL) { + interpListPtr = interpListPtr->nextPtr; + } else { + prevPtr->nextPtr = riPtr->nextPtr; + } + break; + } + } + + /* + * Pick a name to use for the application. Use "name" if it's not + * already in use. Otherwise add a suffix such as " #2", trying + * larger and larger numbers until we eventually find one that is + * unique. + */ + + actualName = name; + suffix = 1; + offset = 0; + Tcl_DStringInit(&dString); + + TkGetInterpNames(interp, tkwin); + resultObjPtr = Tcl_GetObjResult(interp); + Tcl_IncrRefCount(resultObjPtr); + for (i = 0; ; ) { + result = Tcl_ListObjIndex(NULL, resultObjPtr, i, &interpNamePtr); + if (interpNamePtr == NULL) { + break; + } + interpName = Tcl_GetStringFromObj(interpNamePtr, NULL); + if (strcmp(actualName, interpName) == 0) { + if (suffix == 1) { + Tcl_DStringAppend(&dString, name, -1); + Tcl_DStringAppend(&dString, " #", 2); + offset = Tcl_DStringLength(&dString); + Tcl_DStringSetLength(&dString, offset + 10); + actualName = Tcl_DStringValue(&dString); + } + suffix++; + sprintf(Tcl_DStringValue(&dString) + offset, "%d", suffix); + i = 0; + } else { + i++; + } + } + + Tcl_DecrRefCount(resultObjPtr); + Tcl_ResetResult(interp); + + /* + * We have found a unique name. Now add it to the registry. + */ + + riPtr = (RegisteredInterp *) ckalloc(sizeof(RegisteredInterp)); + riPtr->interp = interp; + riPtr->name = ckalloc(strlen(actualName) + 1); + riPtr->nextPtr = interpListPtr; + interpListPtr = riPtr; + strcpy(riPtr->name, actualName); + + Tcl_CreateObjCommand(interp, "send", Tk_SendObjCmd, + (ClientData) riPtr, NULL /* TODO: DeleteProc */); + if (Tcl_IsSafe(interp)) { + Tcl_HideCommand(interp, "send", "send"); + } + Tcl_DStringFree(&dString); + + return riPtr->name; +} + +/* + *-------------------------------------------------------------- + * + * Tk_SendObjCmd -- + * + * This procedure is invoked to process the "send" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *-------------------------------------------------------------- + */ + +int +Tk_SendObjCmd( + ClientData clientData, /* Used only for deletion */ + Tcl_Interp *interp, /* The interp we are sending from */ + int objc, /* Number of arguments */ + Tcl_Obj *CONST objv[]) /* The arguments */ +{ + CONST char *sendOptions[] = {"-async", "-displayof", "-", (char *) NULL}; + char *stringRep, *destName; + int async = 0; + int i, index, firstArg; + RegisteredInterp *riPtr; + Tcl_Obj *resultPtr, *listObjPtr; + int result = TCL_OK; + + for (i = 1; i < (objc - 1); ) { + stringRep = Tcl_GetStringFromObj(objv[i], NULL); + if (stringRep[0] == '-') { + if (Tcl_GetIndexFromObj(interp, objv[i], sendOptions, "option", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + if (index == 0) { + async = 1; + i++; + } else if (index == 1) { + i += 2; + } else { + i++; + } + } else { + break; + } + } + + if (objc < (i + 2)) { + Tcl_WrongNumArgs(interp, 1, objv, + "?options? interpName arg ?arg ...?"); + return TCL_ERROR; + } + + destName = Tcl_GetStringFromObj(objv[i], NULL); + firstArg = i + 1; + + resultPtr = Tcl_GetObjResult(interp); + + /* + * See if the target interpreter is local. If so, execute + * the command directly without going through the DDE server. + * The only tricky thing is passing the result from the target + * interpreter to the invoking interpreter. Watch out: they + * could be the same! + */ + + for (riPtr = interpListPtr; (riPtr != NULL) + && (strcmp(destName, riPtr->name)); riPtr = riPtr->nextPtr) { + /* + * Empty loop body. + */ + + } + + if (riPtr != NULL) { + /* + * This command is to a local interp. No need to go through + * the server. + */ + + Tcl_Interp *localInterp; + + Tcl_Preserve((ClientData) riPtr); + localInterp = riPtr->interp; + Tcl_Preserve((ClientData) localInterp); + if (firstArg == (objc - 1)) { + /* + * This might be one of those cases where the new + * parser is faster. + */ + + result = Tcl_EvalObjEx(localInterp, objv[firstArg], TCL_EVAL_DIRECT); + } else { + listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); + for (i = firstArg; i < objc; i++) { + Tcl_ListObjAppendList(interp, listObjPtr, objv[i]); + } + Tcl_IncrRefCount(listObjPtr); + result = Tcl_EvalObjEx(localInterp, listObjPtr, TCL_EVAL_DIRECT); + Tcl_DecrRefCount(listObjPtr); + } + if (interp != localInterp) { + if (result == TCL_ERROR) { + /* Tcl_Obj *errorObjPtr; */ + + /* + * An error occurred, so transfer error information from the + * destination interpreter back to our interpreter. Must clear + * interp's result before calling Tcl_AddErrorInfo, since + * Tcl_AddErrorInfo will store the interp's result in errorInfo + * before appending riPtr's $errorInfo; we've already got + * everything we need in riPtr's $errorInfo. + */ + + Tcl_ResetResult(interp); + Tcl_AddErrorInfo(interp, Tcl_GetVar2(localInterp, + "errorInfo", (char *) NULL, TCL_GLOBAL_ONLY)); + /* errorObjPtr = Tcl_GetObjVar2(localInterp, "errorCode", NULL, + TCL_GLOBAL_ONLY); + Tcl_SetObjErrorCode(interp, errorObjPtr); */ + } + Tcl_SetObjResult(interp, Tcl_GetObjResult(localInterp)); + } + Tcl_Release((ClientData) riPtr); + Tcl_Release((ClientData) localInterp); + } else { + /* + * This is a non-local request. Send the script to the server and poll + * it for a result. TODO!!! + */ + } + + return result; +} + +/* + *---------------------------------------------------------------------- + * + * TkGetInterpNames -- + * + * This procedure is invoked to fetch a list of all the + * interpreter names currently registered for the display + * of a particular window. + * + * Results: + * A standard Tcl return value. Interp->result will be set + * to hold a list of all the interpreter names defined for + * tkwin's display. If an error occurs, then TCL_ERROR + * is returned and interp->result will hold an error message. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkGetInterpNames( + Tcl_Interp *interp, /* Interpreter for returning a result. */ + Tk_Window tkwin) /* Window whose display is to be used + * for the lookup. */ +{ + Tcl_Obj *listObjPtr; + RegisteredInterp *riPtr; + + listObjPtr = Tcl_NewListObj(0, (Tcl_Obj **) NULL); + riPtr = interpListPtr; + while (riPtr != NULL) { + Tcl_ListObjAppendElement(interp, listObjPtr, + Tcl_NewStringObj(riPtr->name, -1)); + riPtr = riPtr->nextPtr; + } + + Tcl_SetObjResult(interp, listObjPtr); + return TCL_OK; +} + +/* + *-------------------------------------------------------------- + * + * SendInit -- + * + * This procedure is called to initialize the + * communication channels for sending commands and + * receiving results. + * + * Results: + * None. + * + * Side effects: + * Sets up various data structures and windows. + * + *-------------------------------------------------------------- + */ + +static int +SendInit( + Tcl_Interp *interp) /* Interpreter to use for error reporting + * (no errors are ever returned, but the + * interpreter is needed anyway). */ +{ + return TCL_OK; +} diff --git a/macosx/tkMacOSXSubwindows.c b/macosx/tkMacOSXSubwindows.c new file mode 100644 index 0000000..380725f --- /dev/null +++ b/macosx/tkMacOSXSubwindows.c @@ -0,0 +1,1304 @@ +/* + * tkMacOSXSubwindows.c -- + * + * Implements subwindows for the macintosh version of Tk. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkMacOSXSubwindows.c,v 1.2 2002/08/31 06:12:30 das Exp $ + */ + +#include "tkInt.h" +#include "X11/X.h" +#include "X11/Xlib.h" +#include <stdio.h> + +#include <Carbon/Carbon.h> +#include "tkMacOSXInt.h" +#include "tkMacOSXDebug.h" + +/* + * Temporary region that can be reused. + */ +static RgnHandle tmpRgn = NULL; + +static void UpdateOffsets _ANSI_ARGS_((TkWindow *winPtr, int deltaX, int deltaY)); + +/* + *---------------------------------------------------------------------- + * + * XDestroyWindow -- + * + * Dealocates the given X Window. + * + * Results: + * The window id is returned. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +XDestroyWindow( + Display* display, /* Display. */ + Window window) /* Window. */ +{ + MacDrawable *macWin = (MacDrawable *) window; + CGrafPtr destPort; + /* + * Remove any dangling pointers that may exist if + * the window we are deleting is being tracked by + * the grab code. + */ + + TkPointerDeadWindow(macWin->winPtr); + macWin->toplevel->referenceCount--; + + + if (Tk_IsTopLevel(macWin->winPtr)) { + DisposeRgn(macWin->clipRgn); + DisposeRgn(macWin->aboveClipRgn); + + /* + * Delete the Mac window and remove it from the windowTable. + * The window could be NULL if the window was never mapped. + * However, we don't do this for embedded windows, they don't + * go in the window list, and they do not own their portPtr's. + */ + + if (!(Tk_IsEmbedded(macWin->winPtr))) { + destPort = TkMacOSXGetDrawablePort(window); + if (destPort != NULL) { + TkMacOSXWindowList *listPtr, *prevPtr; + WindowRef winRef; + winRef = GetWindowFromPort(destPort); + TkMacOSXUnregisterMacWindow(winRef); + DisposeWindow(winRef); + + for (listPtr = tkMacOSXWindowListPtr, prevPtr = NULL; + tkMacOSXWindowListPtr != NULL; + prevPtr = listPtr, listPtr = listPtr->nextPtr) { + if (listPtr->winPtr == macWin->winPtr) { + if (prevPtr == NULL) { + tkMacOSXWindowListPtr = listPtr->nextPtr; + } else { + prevPtr->nextPtr = listPtr->nextPtr; + } + ckfree((char *) listPtr); + break; + } + } + } + } + + macWin->grafPtr = NULL; + + /* + * Delay deletion of a toplevel data structure untill all + * children have been deleted. + */ + if (macWin->toplevel->referenceCount == 0) { + ckfree((char *) macWin->toplevel); + } + } else { + CGrafPtr destPort; + destPort = TkMacOSXGetDrawablePort(window); + if (destPort != NULL) { + SetGWorld(destPort, NULL); + TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); + } + if (macWin->winPtr->parentPtr != NULL) { + TkMacOSXInvalClipRgns(macWin->winPtr->parentPtr); + } + DisposeRgn(macWin->clipRgn); + DisposeRgn(macWin->aboveClipRgn); + + if (macWin->toplevel->referenceCount == 0) { + ckfree((char *) macWin->toplevel); + } + ckfree((char *) macWin); + } +} + +/* + *---------------------------------------------------------------------- + * + * XMapWindow -- + * + * Map the given X Window to the screen. See X window documentation + * for more details. + * + * Results: + * None. + * + * Side effects: + * The subwindow or toplevel may appear on the screen. + * + *---------------------------------------------------------------------- + */ + +void +XMapWindow( + Display* display, /* Display. */ + Window window) /* Window. */ +{ + MacDrawable *macWin = (MacDrawable *) window; + XEvent event; + CGrafPtr destPort; + + /* + * Under certain situations it's possible for this function to be + * called before the toplevel window it's associated with has actually + * been mapped. In that case we need to create the real Macintosh + * window now as this function as well as other X functions assume that + * the portPtr is valid. + */ + if (!TkMacOSXHostToplevelExists(macWin->toplevel->winPtr)) { + TkMacOSXMakeRealWindowExist(macWin->toplevel->winPtr); + } + destPort = TkMacOSXGetDrawablePort (window); + + display->request++; + macWin->winPtr->flags |= TK_MAPPED; + if (Tk_IsTopLevel(macWin->winPtr)) { + if (!Tk_IsEmbedded(macWin->winPtr)) { + ShowWindow(GetWindowFromPort(destPort)); + } + + /* + * We only need to send the MapNotify event + * for toplevel windows. + */ + event.xany.serial = display->request; + event.xany.send_event = False; + event.xany.display = display; + + event.xmap.window = window; + event.xmap.type = MapNotify; + event.xmap.event = window; + event.xmap.override_redirect = macWin->winPtr->atts.override_redirect; + Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); + } else { + TkMacOSXInvalClipRgns(macWin->winPtr->parentPtr); + } + + /* + * Generate damage for that area of the window + */ + SetGWorld (destPort, NULL); + TkMacOSXUpdateClipRgn(macWin->winPtr); + TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); +} + +/* + *---------------------------------------------------------------------- + * + * XUnmapWindow -- + * + * Unmap the given X Window to the screen. See X window + * documentation for more details. + * + * Results: + * None. + * + * Side effects: + * The subwindow or toplevel may be removed from the screen. + * + *---------------------------------------------------------------------- + */ + +void +XUnmapWindow( + Display* display, /* Display. */ + Window window) /* Window. */ +{ + MacDrawable *macWin = (MacDrawable *) window; + XEvent event; + CGrafPtr destPort; + + destPort = TkMacOSXGetDrawablePort(window); + + display->request++; + macWin->winPtr->flags &= ~TK_MAPPED; + if (Tk_IsTopLevel(macWin->winPtr)) { + if (!Tk_IsEmbedded(macWin->winPtr)) { + HideWindow(GetWindowFromPort(destPort)); + } + + /* + * We only need to send the UnmapNotify event + * for toplevel windows. + */ + event.xany.serial = display->request; + event.xany.send_event = False; + event.xany.display = display; + + event.xunmap.type = UnmapNotify; + event.xunmap.window = window; + event.xunmap.event = window; + event.xunmap.from_configure = false; + Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); + } else { + /* + * Generate damage for that area of the window. + */ + SetGWorld(destPort, NULL); + TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); /* TODO: may not be valid */ + TkMacOSXInvalClipRgns(macWin->winPtr->parentPtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * XResizeWindow -- + * + * Resize a given X window. See X windows documentation for + * further details. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +XResizeWindow( + Display* display, /* Display. */ + Window window, /* Window. */ + unsigned int width, + unsigned int height) +{ + MacDrawable *macWin = (MacDrawable *) window; + CGrafPtr destPort; + + destPort = TkMacOSXGetDrawablePort(window); + if (destPort == NULL) { + return; + } + + display->request++; + SetPort( destPort); + if (Tk_IsTopLevel(macWin->winPtr)) { + if (!Tk_IsEmbedded(macWin->winPtr)) { + /* + * NOTE: we are not adding the new space to the update + * region. It is currently assumed that Tk will need + * to completely redraw anway. + */ + SizeWindow(GetWindowFromPort(destPort), + (short) width, (short) height, false); + TkMacOSXInvalidateWindow(macWin, TK_WINDOW_ONLY); + TkMacOSXInvalClipRgns(macWin->winPtr); + } else { + int deltaX, deltaY; + + /* + * Find the Parent window - + * For an embedded window this will be its container. + */ + TkWindow *contWinPtr; + + contWinPtr = TkpGetOtherWindow(macWin->winPtr); + + if (contWinPtr != NULL) { + MacDrawable *macParent = contWinPtr->privatePtr; + + TkMacOSXInvalClipRgns(macParent->winPtr); + TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); + + deltaX = macParent->xOff + + macWin->winPtr->changes.x - macWin->xOff; + deltaY = macParent->yOff + + macWin->winPtr->changes.y - macWin->yOff; + + UpdateOffsets(macWin->winPtr, deltaX, deltaY); + } else { + /* + * This is the case where we are embedded in + * another app. At this point, we are assuming that + * the changes.x,y is not maintained, if you need + * the info get it from Tk_GetRootCoords, + * and that the toplevel sits at 0,0 when it is drawn. + */ + + TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); + UpdateOffsets(macWin->winPtr, 0, 0); + } + + } + } else { + /* TODO: update all xOff & yOffs */ + int deltaX, deltaY, parentBorderwidth; + MacDrawable *macParent = macWin->winPtr->parentPtr->privatePtr; + + if (macParent == NULL) { + return; /* TODO: Probably should be a panic */ + } + + TkMacOSXInvalClipRgns(macParent->winPtr); + TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); + + deltaX = - macWin->xOff; + deltaY = - macWin->yOff; + + parentBorderwidth = macWin->winPtr->parentPtr->changes.border_width; + + deltaX += macParent->xOff + parentBorderwidth + + macWin->winPtr->changes.x; + deltaY += macParent->yOff + parentBorderwidth + + macWin->winPtr->changes.y; + + UpdateOffsets(macWin->winPtr, deltaX, deltaY); + } +} + +/* + *---------------------------------------------------------------------- + * + * XMoveResizeWindow -- + * + * Move or resize a given X window. See X windows documentation + * for further details. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +XMoveResizeWindow( + Display* display, /* Display. */ + Window window, /* Window. */ + int x, int y, + unsigned int width, + unsigned int height) +{ + MacDrawable * macWin = (MacDrawable *) window; + CGrafPtr destPort; + + destPort = TkMacOSXGetDrawablePort(window); + if (destPort == NULL) { + return; + } + + SetPort( destPort); + if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) { + /* + * NOTE: we are not adding the new space to the update + * region. It is currently assumed that Tk will need + * to completely redraw anway. + */ + + SizeWindow(GetWindowFromPort(destPort), + (short) width, (short) height, false); + MoveWindowStructure(GetWindowFromPort(destPort), x, y); + + /* TODO: is the following right? */ + TkMacOSXInvalidateWindow(macWin, TK_WINDOW_ONLY); + TkMacOSXInvalClipRgns(macWin->winPtr); + } else { + int deltaX, deltaY, parentBorderwidth; + Rect bounds; + MacDrawable *macParent; + + /* + * Find the Parent window - + * For an embedded window this will be its container. + */ + + if (Tk_IsEmbedded(macWin->winPtr)) { + TkWindow *contWinPtr; + + contWinPtr = TkpGetOtherWindow(macWin->winPtr); + if (contWinPtr == NULL) { + panic("XMoveResizeWindow could not find container"); + } + macParent = contWinPtr->privatePtr; + + /* + * NOTE: Here we should handle out of process embedding. + */ + + + } else { + macParent = macWin->winPtr->parentPtr->privatePtr; + if (macParent == NULL) { + return; /* TODO: Probably should be a panic */ + } + } + + TkMacOSXInvalClipRgns(macParent->winPtr); + TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); + + deltaX = - macWin->xOff; + deltaY = - macWin->yOff; + + /* + * If macWin->winPtr is an embedded window, don't offset by its + * parent's borderwidth... + */ + + if (!Tk_IsEmbedded(macWin->winPtr)) { + parentBorderwidth = macWin->winPtr->parentPtr->changes.border_width; + } else { + parentBorderwidth = 0; + } + deltaX += macParent->xOff + parentBorderwidth + + macWin->winPtr->changes.x; + deltaY += macParent->yOff + parentBorderwidth + + macWin->winPtr->changes.y; + + UpdateOffsets(macWin->winPtr, deltaX, deltaY); + TkMacOSXWinBounds(macWin->winPtr, &bounds); + InvalWindowRect(GetWindowFromPort(destPort),&bounds); + } +} + +/* + *---------------------------------------------------------------------- + * + * XMoveWindow -- + * + * Move a given X window. See X windows documentation for further + * details. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +XMoveWindow( + Display* display, /* Display. */ + Window window, /* Window. */ + int x, + int y) +{ + MacDrawable *macWin = (MacDrawable *) window; + CGrafPtr destPort; + + destPort = TkMacOSXGetDrawablePort(window); + if (destPort == NULL) { + return; + } + + SetPort( destPort); + if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) { + /* + * NOTE: we are not adding the new space to the update + * region. It is currently assumed that Tk will need + * to completely redraw anway. + */ + MoveWindowStructure( GetWindowFromPort(destPort), x, y); + + /* TODO: is the following right? */ + TkMacOSXInvalidateWindow(macWin, TK_WINDOW_ONLY); + TkMacOSXInvalClipRgns(macWin->winPtr); + } else { + int deltaX, deltaY, parentBorderwidth; + Rect bounds; + MacDrawable *macParent; + + /* + * Find the Parent window - + * For an embedded window this will be its container. + */ + + if (Tk_IsEmbedded(macWin->winPtr)) { + TkWindow *contWinPtr; + + contWinPtr = TkpGetOtherWindow(macWin->winPtr); + if (contWinPtr == NULL) { + panic("XMoveWindow could not find container"); + } + macParent = contWinPtr->privatePtr; + + /* + * NOTE: Here we should handle out of process embedding. + */ + + } else { + macParent = macWin->winPtr->parentPtr->privatePtr; + if (macParent == NULL) { + return; /* TODO: Probably should be a panic */ + } + } + + TkMacOSXInvalClipRgns(macParent->winPtr); + TkMacOSXInvalidateWindow(macWin, TK_PARENT_WINDOW); + + deltaX = - macWin->xOff; + deltaY = - macWin->yOff; + + /* + * If macWin->winPtr is an embedded window, don't offset by its + * parent's borderwidth... + */ + + if (!Tk_IsEmbedded(macWin->winPtr)) { + parentBorderwidth = macWin->winPtr->parentPtr->changes.border_width; + } else { + parentBorderwidth = 0; + } + deltaX += macParent->xOff + parentBorderwidth + + macWin->winPtr->changes.x; + deltaY += macParent->yOff + parentBorderwidth + + macWin->winPtr->changes.y; + + UpdateOffsets(macWin->winPtr, deltaX, deltaY); + TkMacOSXWinBounds(macWin->winPtr, &bounds); + InvalWindowRect(GetWindowFromPort(destPort),&bounds); + } +} + +/* + *---------------------------------------------------------------------- + * + * XRaiseWindow -- + * + * Change the stacking order of a window. + * + * Results: + * None. + * + * Side effects: + * Changes the stacking order of the specified window. + * + *---------------------------------------------------------------------- + */ + +void +XRaiseWindow( + Display* display, /* Display. */ + Window window) /* Window. */ +{ + MacDrawable *macWin = (MacDrawable *) window; + + display->request++; + if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) { + TkWmRestackToplevel(macWin->winPtr, Above, NULL); + } else { + /* TODO: this should generate damage */ + } +} + +/* + *---------------------------------------------------------------------- + * + * XLowerWindow -- + * + * Change the stacking order of a window. + * + * Results: + * None. + * + * Side effects: + * Changes the stacking order of the specified window. + * + *---------------------------------------------------------------------- + */ + +void +XLowerWindow( + Display* display, /* Display. */ + Window window) /* Window. */ +{ + MacDrawable *macWin = (MacDrawable *) window; + + display->request++; + if (Tk_IsTopLevel(macWin->winPtr) && !Tk_IsEmbedded(macWin->winPtr)) { + TkWmRestackToplevel(macWin->winPtr, Below, NULL); + } else { + /* TODO: this should generate damage */ + } +} + +/* + *---------------------------------------------------------------------- + * + * XConfigureWindow -- + * + * Change the size, position, stacking, or border of the specified + * window. + * + * Results: + * None. + * + * Side effects: + * Changes the attributes of the specified window. Note that we + * ignore the passed in values and use the values stored in the + * TkWindow data structure. + * + *---------------------------------------------------------------------- + */ + +void +XConfigureWindow( + Display* display, /* Display. */ + Window w, /* Window. */ + unsigned int value_mask, + XWindowChanges* values) +{ + MacDrawable *macWin = (MacDrawable *) w; + TkWindow *winPtr = macWin->winPtr; + + display->request++; + + /* + * Change the shape and/or position of the window. + */ + + if (value_mask & (CWX|CWY|CWWidth|CWHeight)) { + XMoveResizeWindow(display, w, winPtr->changes.x, winPtr->changes.y, + winPtr->changes.width, winPtr->changes.height); + } + + /* + * Change the stacking order of the window. Tk actuall keeps all + * the information we need for stacking order. All we need to do + * is make sure the clipping regions get updated and generate damage + * that will ensure things get drawn correctly. + */ + + if (value_mask & CWStackMode) { + Rect bounds; + CGrafPtr destPort; + + destPort = TkMacOSXGetDrawablePort(w); + if (destPort != NULL) { + SetPort( destPort); + TkMacOSXInvalClipRgns(winPtr->parentPtr); + TkMacOSXWinBounds(winPtr, &bounds); + InvalWindowRect(GetWindowFromPort(destPort),&bounds); + } + } + + /* TkGenWMMoveRequestEvent(macWin->winPtr, + macWin->winPtr->changes.x, macWin->winPtr->changes.y); */ +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXUpdateClipRgn -- + * + * This function updates the cliping regions for a given window + * and all of its children. Once updated the TK_CLIP_INVALID flag + * in the subwindow data structure is unset. The TK_CLIP_INVALID + * flag should always be unset before any drawing is attempted. + * + * Results: + * None. + * + * Side effects: + * The clip regions for the window and its children are updated. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXUpdateClipRgn( + TkWindow *winPtr) +{ + RgnHandle rgn; + int x, y; + TkWindow *win2Ptr; + + if (winPtr == NULL) { + return; + } + + if (winPtr->privatePtr->flags & TK_CLIP_INVALID) { + rgn = winPtr->privatePtr->aboveClipRgn; + if (tmpRgn == NULL) { + tmpRgn = NewRgn(); + } + + /* + * Start with a region defined by the window bounds. + */ + + x = winPtr->privatePtr->xOff; + y = winPtr->privatePtr->yOff; + SetRectRgn(rgn, (short) x, (short) y, + (short) (winPtr->changes.width + x), + (short) (winPtr->changes.height + y)); + + /* + * Clip away the area of any windows that may obscure this + * window. + * For a non-toplevel window, first, clip to the parents visable + * clip region. + * Second, clip away any siblings that are higher in the + * stacking order. + * For an embedded toplevel, just clip to the container's visible + * clip region. Remember, we only allow one contained window + * in a frame, and don't support any other widgets in the frame either. + * This is not currently enforced, however. + */ + + if (!Tk_IsTopLevel(winPtr)) { + TkMacOSXUpdateClipRgn(winPtr->parentPtr); + SectRgn(rgn, + winPtr->parentPtr->privatePtr->aboveClipRgn, rgn); + + win2Ptr = winPtr->nextPtr; + while (win2Ptr != NULL) { + if (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) { + win2Ptr = win2Ptr->nextPtr; + continue; + } + x = win2Ptr->privatePtr->xOff; + y = win2Ptr->privatePtr->yOff; + SetRectRgn(tmpRgn, (short) x, (short) y, + (short) (win2Ptr->changes.width + x), + (short) (win2Ptr->changes.height + y)); + DiffRgn(rgn, tmpRgn, rgn); + + win2Ptr = win2Ptr->nextPtr; + } + } else if (Tk_IsEmbedded(winPtr)) { + TkWindow *contWinPtr; + + contWinPtr = TkpGetOtherWindow(winPtr); + + if (contWinPtr != NULL) { + TkMacOSXUpdateClipRgn(contWinPtr); + SectRgn(rgn, + contWinPtr->privatePtr->aboveClipRgn, rgn); + } else if (gMacEmbedHandler != NULL) { + gMacEmbedHandler->getClipProc((Tk_Window) winPtr, tmpRgn); + SectRgn(rgn, tmpRgn, rgn); + } + + /* + * NOTE: Here we should handle out of process embedding. + */ + + } + + /* + * The final clip region is the aboveClip region (or visable + * region) minus all the children of this window. + * Alternatively, if the window is a container, we must also + * subtract the region of the embedded window. + */ + + rgn = winPtr->privatePtr->clipRgn; + CopyRgn(winPtr->privatePtr->aboveClipRgn, rgn); + + win2Ptr = winPtr->childList; + while (win2Ptr != NULL) { + if (Tk_IsTopLevel(win2Ptr) || !Tk_IsMapped(win2Ptr)) { + win2Ptr = win2Ptr->nextPtr; + continue; + } + x = win2Ptr->privatePtr->xOff; + y = win2Ptr->privatePtr->yOff; + SetRectRgn(tmpRgn, (short) x, (short) y, + (short) (win2Ptr->changes.width + x), + (short) (win2Ptr->changes.height + y)); + DiffRgn(rgn, tmpRgn, rgn); + + win2Ptr = win2Ptr->nextPtr; + } + + if (Tk_IsContainer(winPtr)) { + win2Ptr = TkpGetOtherWindow(winPtr); + if (win2Ptr != NULL) { + if (Tk_IsMapped(win2Ptr)) { + x = win2Ptr->privatePtr->xOff; + y = win2Ptr->privatePtr->yOff; + SetRectRgn(tmpRgn, (short) x, (short) y, + (short) (win2Ptr->changes.width + x), + (short) (win2Ptr->changes.height + y)); + DiffRgn(rgn, tmpRgn, rgn); + } + } + + /* + * NOTE: Here we should handle out of process embedding. + */ + + } + + winPtr->privatePtr->flags &= ~TK_CLIP_INVALID; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXVisableClipRgn -- + * + * This function returnd the Macintosh cliping region for the + * given window. A NULL Rgn means the window is not visable. + * + * Results: + * The region. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +RgnHandle +TkMacOSXVisableClipRgn( + TkWindow *winPtr) +{ + if (winPtr->privatePtr->flags & TK_CLIP_INVALID) { + TkMacOSXUpdateClipRgn(winPtr); + } + + return winPtr->privatePtr->clipRgn; +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXInvalidateWindow -- + * + * This function makes the window as invalid will generate damage + * for the window. + * + * Results: + * None. + * + * Side effects: + * Damage is created. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXInvalidateWindow( + MacDrawable *macWin, /* Make window that's causing damage. */ + int flag) /* Should be TK_WINDOW_ONLY or + * TK_PARENT_WINDOW */ +{ + WindowRef windowRef; + CGrafPtr grafPtr; + + grafPtr=TkMacOSXGetDrawablePort((Drawable)macWin); + windowRef=GetWindowFromPort(grafPtr); + + if (flag == TK_WINDOW_ONLY) { + InvalWindowRgn(windowRef,macWin->clipRgn); + } else { + if (!EmptyRgn(macWin->aboveClipRgn)) { + InvalWindowRgn(windowRef,macWin->aboveClipRgn); + } + } +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXGetDrawablePort -- + * + * This function returns the Graphics Port for a given X drawable. + * + * Results: + * A CGrafPort . Either an off screen pixmap or a Window. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +CGrafPtr +TkMacOSXGetDrawablePort( + Drawable drawable) +{ + MacDrawable *macWin = (MacDrawable *) drawable; + GWorldPtr resultPort = NULL; + + if (macWin == NULL) { + return NULL; + } + + /* + * This is NULL for off-screen pixmaps. Then the portPtr + * always points to the off-screen port, and we don't + * have to worry about containment + */ + + if (macWin->clipRgn == NULL) { + return macWin->grafPtr; + } + + /* + * If the Drawable is in an embedded window, use the Port of its container. + * + * TRICKY POINT: we can have cases when a toplevel is being destroyed + * where the winPtr for the toplevel has been freed, but the children + * are not all the way destroyed. The children will call this function + * as they are being destroyed, but Tk_IsEmbedded will return garbage. + * So we check the copy of the TK_EMBEDDED flag we put into the + * toplevel's macWin flags. + */ + + + + + if (!(macWin->toplevel->flags & TK_EMBEDDED)) { + return macWin->toplevel->grafPtr; + } else { + TkWindow *contWinPtr; + + contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr); + + if (contWinPtr != NULL) { + resultPort = TkMacOSXGetDrawablePort( + (Drawable) contWinPtr->privatePtr); + } else if (gMacEmbedHandler != NULL) { + resultPort = gMacEmbedHandler->getPortProc( + (Tk_Window) macWin->winPtr); + } + + if (resultPort == NULL) { + /* + * FIXME: + * + * So far as I can tell, the only time that this happens is when + * we are tearing down an embedded child interpreter, and most + * of the time, this is harmless... However, we really need to + * find why the embedding loses. + */ + DebugStr("\pTkMacOSXGetDrawablePort couldn't find container"); + return NULL; + } + + /* + * NOTE: Here we should handle out of process embedding. + */ + + } + return resultPort; +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXGetRootControl -- + * + * This function returns the Root Control for a given X drawable. + * + * Results: + * A ControlRef . + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +ControlRef +TkMacOSXGetRootControl( + Drawable drawable) +{ + /* + * will probably need to fix this up for embedding + */ + MacDrawable *macWin = (MacDrawable *) drawable; + ControlRef result = NULL; + + if (macWin == NULL) { + return NULL; + } + if (!(macWin->toplevel->flags & TK_EMBEDDED)) { + return macWin->toplevel->rootControl; + } else { + TkWindow *contWinPtr; + + contWinPtr = TkpGetOtherWindow(macWin->toplevel->winPtr); + + if (contWinPtr != NULL) { + result = TkMacOSXGetRootControl( + (Drawable) contWinPtr->privatePtr); + } else if (gMacEmbedHandler != NULL) { + result = NULL; + } + } + return result; +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXInvalClipRgns -- + * + * This function invalidates the clipping regions for a given + * window and all of its children. This function should be + * called whenever changes are made to subwindows that would + * effect the size or position of windows. + * + * Results: + * None. + * + * Side effects: + * The cliping regions for the window and its children are + * mark invalid. (Make sure they are valid before drawing.) + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXInvalClipRgns( + TkWindow *winPtr) +{ + TkWindow *childPtr; + + /* + * If already marked we can stop because all + * decendants will also already be marked. + */ + if (winPtr->privatePtr->flags & TK_CLIP_INVALID) { + return; + } + + winPtr->privatePtr->flags |= TK_CLIP_INVALID; + + /* + * Invalidate clip regions for all children & + * their decendants - unless the child is a toplevel. + */ + childPtr = winPtr->childList; + while (childPtr != NULL) { + if (!Tk_IsTopLevel(childPtr) && Tk_IsMapped(childPtr)) { + TkMacOSXInvalClipRgns(childPtr); + } + childPtr = childPtr->nextPtr; + } + + /* + * Also, if the window is a container, mark its embedded window + */ + + if (Tk_IsContainer(winPtr)) { + childPtr = TkpGetOtherWindow(winPtr); + + if (childPtr != NULL && Tk_IsMapped(childPtr)) { + TkMacOSXInvalClipRgns(childPtr); + } + + /* + * NOTE: Here we should handle out of process embedding. + */ + + } +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXWinBounds -- + * + * Given a Tk window this function determines the windows + * bounds in relation to the Macintosh window's coordinate + * system. This is also the same coordinate system as the + * Tk toplevel window in which this window is contained. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXWinBounds( + TkWindow *winPtr, + Rect *bounds) +{ + bounds->left = (short) winPtr->privatePtr->xOff; + bounds->top = (short) winPtr->privatePtr->yOff; + bounds->right = (short) (winPtr->privatePtr->xOff + + winPtr->changes.width); + bounds->bottom = (short) (winPtr->privatePtr->yOff + + winPtr->changes.height); +} +/* + *---------------------------------------------------------------------- + * + * UpdateOffsets -- + * + * Updates the X & Y offsets of the given TkWindow from the + * TopLevel it is a decendant of. + * + * Results: + * None. + * + * Side effects: + * The xOff & yOff fields for the Mac window datastructure + * is updated to the proper offset. + * + *---------------------------------------------------------------------- + */ + +static void +UpdateOffsets( + TkWindow *winPtr, + int deltaX, + int deltaY) +{ + TkWindow *childPtr; + + if (winPtr->privatePtr == NULL) { + /* + * We havn't called Tk_MakeWindowExist for this window yet. The + * offset information will be postponed and calulated at that + * time. (This will usually only happen when a mapped parent is + * being moved but has child windows that have yet to be mapped.) + */ + return; + } + + winPtr->privatePtr->xOff += deltaX; + winPtr->privatePtr->yOff += deltaY; + + childPtr = winPtr->childList; + while (childPtr != NULL) { + if (!Tk_IsTopLevel(childPtr)) { + UpdateOffsets(childPtr, deltaX, deltaY); + } + childPtr = childPtr->nextPtr; + } + + if (Tk_IsContainer(winPtr)) { + childPtr = TkpGetOtherWindow(winPtr); + if (childPtr != NULL) { + UpdateOffsets(childPtr,deltaX,deltaY); + } + + /* + * NOTE: Here we should handle out of process embedding. + */ + + } +} + +/* + *---------------------------------------------------------------------- + * + * Tk_GetPixmap -- + * + * Creates an in memory drawing surface. + * + * Results: + * Returns a handle to a new pixmap. + * + * Side effects: + * Allocates a new Macintosh GWorld. + * + *---------------------------------------------------------------------- + */ + +Pixmap +Tk_GetPixmap( + Display *display, /* Display for new pixmap (can be null). */ + Drawable d, /* Drawable where pixmap will be used (ignored). */ + int width, /* Dimensions of pixmap. */ + int height, + int depth) /* Bits per pixel for pixmap. */ +{ + QDErr err; + GWorldPtr gWorld; + Rect bounds; + MacDrawable *macPix; + PixMapHandle pixels; + + if (display != NULL) { + display->request++; + } + macPix = (MacDrawable *) ckalloc(sizeof(MacDrawable)); + macPix->winPtr = NULL; + macPix->xOff = 0; + macPix->yOff = 0; + macPix->clipRgn = NULL; + macPix->aboveClipRgn = NULL; + macPix->referenceCount = 0; + macPix->toplevel = NULL; + macPix->flags = 0; + + bounds.top = bounds.left = 0; + bounds.right = (short) width; + bounds.bottom = (short) height; + if (depth != 1) { + depth = 0; + } + /* + * Allocate memory for the off screen pixmap. If we fail + * try again from system memory. Eventually, we may have + * to panic. + */ + err = NewGWorld(&gWorld, depth, &bounds, NULL, NULL, 0); + if (err != noErr) { + err = NewGWorld(&gWorld, depth, &bounds, NULL, NULL, useTempMem); + } + if (err != noErr) { + panic("Out of memory: NewGWorld failed in Tk_GetPixmap"); + } + + /* + * Lock down the pixels so they don't move out from under us. + */ + pixels = GetGWorldPixMap(gWorld); + LockPixels(pixels); + macPix->grafPtr = gWorld; + + return (Pixmap) macPix; +} + +/* + *---------------------------------------------------------------------- + * + * Tk_FreePixmap -- + * + * Release the resources associated with a pixmap. + * + * Results: + * None. + * + * Side effects: + * Deletes the Macintosh GWorld created by Tk_GetPixmap. + * + *---------------------------------------------------------------------- + */ + +void +Tk_FreePixmap( + Display *display, /* Display. */ + Pixmap pixmap) /* Pixmap to destroy */ +{ + MacDrawable *macPix = (MacDrawable *) pixmap; + PixMapHandle pixels; + + display->request++; + pixels = GetGWorldPixMap(macPix->grafPtr); + UnlockPixels(pixels); + DisposeGWorld(macPix->grafPtr); + ckfree((char *) macPix); +} diff --git a/macosx/tkMacOSXTest.c b/macosx/tkMacOSXTest.c new file mode 100644 index 0000000..02cad5f --- /dev/null +++ b/macosx/tkMacOSXTest.c @@ -0,0 +1,82 @@ +/* + * tkMacOSXTest.c -- + * + * Contains commands for platform specific tests for + * the Macintosh platform. + * + * Copyright (c) 1996 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkMacOSXTest.c,v 1.2 2002/08/31 06:12:30 das Exp $ + */ + +#include <tcl.h> + +/* + * Forward declarations of procedures defined later in this file: + */ + +int TkplatformtestInit _ANSI_ARGS_((Tcl_Interp *interp)); +static int DebuggerCmd _ANSI_ARGS_((ClientData dummy, + Tcl_Interp *interp, int argc, char **argv)); + +/* + *---------------------------------------------------------------------- + * + * TkplatformtestInit -- + * + * Defines commands that test platform specific functionality for + * Unix platforms. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * Defines new commands. + * + *---------------------------------------------------------------------- + */ + +int +TkplatformtestInit( + Tcl_Interp *interp) /* Interpreter to add commands to. */ +{ + /* + * Add commands for platform specific tests on MacOS here. + */ + + Tcl_CreateCommand(interp, "debugger", DebuggerCmd, + (ClientData) 0, (Tcl_CmdDeleteProc *) NULL); + + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * DebuggerCmd -- + * + * This procedure simply calls the low level debugger. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static int +DebuggerCmd( + ClientData clientData, /* Not used. */ + Tcl_Interp *interp, /* Not used. */ + int argc, /* Not used. */ + char **argv) /* Not used. */ +{ + Debugger(); + return TCL_OK; +} diff --git a/macosx/tkMacOSXUtil.c b/macosx/tkMacOSXUtil.c new file mode 100644 index 0000000..1e4e856 --- /dev/null +++ b/macosx/tkMacOSXUtil.c @@ -0,0 +1,330 @@ +#include <Carbon/Carbon.h> + +#include "tkMacOSXUtil.h" + +#define DIR_SEP_CHAR ':' + +/*****************************************************************************/ +pascal OSErr FSMakeFSSpecCompat(short vRefNum, + long dirID, + ConstStr255Param fileName, + FSSpec *spec) +{ + OSErr result; + + { + /* Let the file system create the FSSpec if it can since it does the job */ + /* much more efficiently than I can. */ + result = FSMakeFSSpec(vRefNum, dirID, fileName, spec); + /* Fix a bug in Macintosh PC Exchange's MakeFSSpec code where 0 is */ + /* returned in the parID field when making an FSSpec to the volume's */ + /* root directory by passing a full pathname in MakeFSSpec's */ + /* fileName parameter. Fixed in Mac OS 8.1 */ + if ( (result == noErr) && (spec->parID == 0) ) + spec->parID = fsRtParID; + } + return ( result ); +} + + +/*****************************************************************************/ +pascal OSErr GetCatInfoNoName(short vRefNum, + long dirID, + ConstStr255Param name, + CInfoPBPtr pb) +{ + Str31 tempName; + OSErr error; + + /* Protection against File Sharing problem */ + if ( (name == NULL) || (name[0] == 0) ) + { + tempName[0] = 0; + pb->dirInfo.ioNamePtr = tempName; + pb->dirInfo.ioFDirIndex = -1; /* use ioDirID */ + } + else + { + pb->dirInfo.ioNamePtr = (StringPtr)name; + pb->dirInfo.ioFDirIndex = 0; /* use ioNamePtr and ioDirID */ + } + pb->dirInfo.ioVRefNum = vRefNum; + pb->dirInfo.ioDrDirID = dirID; + error = PBGetCatInfoSync(pb); + pb->dirInfo.ioNamePtr = NULL; + return ( error ); +} +/*****************************************************************************/ +pascal OSErr GetDirectoryID(short vRefNum, + long dirID, + ConstStr255Param name, + long *theDirID, + Boolean *isDirectory) +{ + CInfoPBRec pb; + OSErr error; + error = GetCatInfoNoName(vRefNum, dirID, name, &pb); + if ( error == noErr ) + { + *isDirectory = (pb.hFileInfo.ioFlAttrib & kioFlAttribDirMask) != 0; + if ( *isDirectory ) + { + *theDirID = pb.dirInfo.ioDrDirID; + } + else + { + *theDirID = pb.hFileInfo.ioFlParID; + } + } + + return ( error ); +} + +/*****************************************************************************/ +pascal OSErr FSpGetDirectoryID(const FSSpec *spec, + long *theDirID, + Boolean *isDirectory) +{ + return ( GetDirectoryID(spec->vRefNum, spec->parID, spec->name, + theDirID, isDirectory) ); +} + +/* + *---------------------------------------------------------------------- + * + * FSpPathFromLocation -- + * + * This function obtains a full path name for a given macintosh + * FSSpec. Unlike the More Files function FSpGetFullPath, this + * function will return a C string in the Handle. It also will + * create paths for FSSpec that do not yet exist. + * + * Results: + * OSErr code. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +OSErr +FSpPathFromLocation( + FSSpec *spec, /* The location we want a path for. */ + int *length, /* Length of the resulting path. */ + Handle *fullPath) /* Handle to path. */ +{ + OSErr err; + FSSpec tempSpec; + CInfoPBRec pb; + + *fullPath = NULL; + + /* + * Make a copy of the input FSSpec that can be modified. + */ + BlockMoveData(spec, &tempSpec, sizeof(FSSpec)); + + if (tempSpec.parID == fsRtParID) { + /* + * The object is a volume. Add a colon to make it a full + * pathname. Allocate a handle for it and we are done. + */ + tempSpec.name[0] += 2; + tempSpec.name[tempSpec.name[0] - 1] = DIR_SEP_CHAR; + tempSpec.name[tempSpec.name[0]] = '\0'; + + err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]); + } else { + /* + * The object isn't a volume. Is the object a file or a directory? + */ + pb.dirInfo.ioNamePtr = tempSpec.name; + pb.dirInfo.ioVRefNum = tempSpec.vRefNum; + pb.dirInfo.ioDrDirID = tempSpec.parID; + pb.dirInfo.ioFDirIndex = 0; + err = PBGetCatInfoSync(&pb); + + if ((err == noErr) || (err == fnfErr)) { + /* + * If the file doesn't currently exist we start over. If the + * directory exists everything will work just fine. Otherwise we + * will just fail later. If the object is a directory, append a + * colon so full pathname ends with colon, but only if the name is + * not empty. NavServices returns FSSpec's with the parent ID set, + * but the name empty... + */ + if (err == fnfErr) { + BlockMoveData(spec, &tempSpec, sizeof(FSSpec)); + } else if ( (pb.hFileInfo.ioFlAttrib & ioDirMask) != 0 ) { + if (tempSpec.name[0] > 0) { + tempSpec.name[0] += 1; + tempSpec.name[tempSpec.name[0]] = DIR_SEP_CHAR; + } + } + + /* + * Create a new Handle for the object - make it a C string. + */ + tempSpec.name[0] += 1; + tempSpec.name[tempSpec.name[0]] = '\0'; + err = PtrToHand(&tempSpec.name[1], fullPath, tempSpec.name[0]); + if (err == noErr) { + /* + * Get the ancestor directory names - loop until we have an + * error or find the root directory. + */ + pb.dirInfo.ioNamePtr = tempSpec.name; + pb.dirInfo.ioVRefNum = tempSpec.vRefNum; + pb.dirInfo.ioDrParID = tempSpec.parID; + do { + pb.dirInfo.ioFDirIndex = -1; + pb.dirInfo.ioDrDirID = pb.dirInfo.ioDrParID; + err = PBGetCatInfoSync(&pb); + if (err == noErr) { + /* + * Append colon to directory name and add + * directory name to beginning of fullPath. + */ + ++tempSpec.name[0]; + tempSpec.name[tempSpec.name[0]] = DIR_SEP_CHAR; + + (void) Munger(*fullPath, 0, NULL, 0, &tempSpec.name[1], + tempSpec.name[0]); + fprintf(stderr,"mem\n"); + err = MemError(); + } + } while ( (err == noErr) && + (pb.dirInfo.ioDrDirID != fsRtDirID) ); + } + } + } + + /* + * On error Dispose the handle, set it to NULL & return the err. + * Otherwise, set the length & return. + */ + if (err == noErr) { + *length = GetHandleSize(*fullPath) - 1; + } else { + if ( *fullPath != NULL ) { + DisposeHandle(*fullPath); + } + *fullPath = NULL; + *length = 0; + } + + return err; +} + +/* + *---------------------------------------------------------------------- + * + * FSpLocationFromPath -- + * + * This function obtains an FSSpec for a given macintosh path. + * Unlike the More Files function FSpLocationFromFullPath, this + * function will also accept partial paths and resolve any aliases + * along the path. + * + * Results: + * OSErr code. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +OSErr +FSpLocationFromPath( + int length, /* Length of path. */ + const char *path, /* The path to convert. */ + FSSpecPtr fileSpecPtr) /* On return the spec for the path. */ +{ + Str255 fileName; + OSErr err; + short vRefNum; + long dirID; + int pos, cur; + Boolean isDirectory; + Boolean wasAlias; + + /* + * Check to see if this is a full path. If partial + * we assume that path starts with the current working + * directory. (Ie. volume & dir = 0) + */ + vRefNum = 0; + dirID = 0; + cur = 0; + if (length == 0) { + return fnfErr; + } + if (path[cur] == DIR_SEP_CHAR) { + cur++; + if (cur >= length) { + /* + * If path = ":", just return current directory. + */ + FSMakeFSSpecCompat(0, 0, NULL, fileSpecPtr); + return noErr; + } + } else { + while (path[cur] != DIR_SEP_CHAR && cur < length) { + cur++; + } + if (cur > 255) { + return bdNamErr; + } + if (cur < length) { + /* + * This is a full path + */ + cur++; + strncpy((char *) fileName + 1, path, cur); + fileName[0] = cur; + err = FSMakeFSSpecCompat(0, 0, fileName, fileSpecPtr); + if (err != noErr) return err; + FSpGetDirectoryID(fileSpecPtr, &dirID, &isDirectory); + vRefNum = fileSpecPtr->vRefNum; + } else { + cur = 0; + } + } + + isDirectory = 1; + while (cur < length) { + if (!isDirectory) { + return dirNFErr; + } + pos = cur; + while (path[pos] != DIR_SEP_CHAR && pos < length) { + pos++; + } + if (pos == cur) { + /* Move up one dir */ + /* cur++; */ + fileName[1] = DIR_SEP_CHAR; + fileName[2] = DIR_SEP_CHAR; + fileName[0] = 2; + } else if (pos - cur > 255) { + return bdNamErr; + } else { + strncpy((char *) fileName + 1, &path[cur], pos - cur); + fileName[0] = pos - cur; + } + err = FSMakeFSSpecCompat(vRefNum, dirID, fileName, fileSpecPtr); + if (err != noErr) return err; + err = ResolveAliasFile(fileSpecPtr, true, &isDirectory, &wasAlias); + if (err != noErr) return err; + FSpGetDirectoryID(fileSpecPtr, &dirID, &isDirectory); + vRefNum = fileSpecPtr->vRefNum; + cur = pos; + if (path[cur] == DIR_SEP_CHAR) { + cur++; + } + } + + return noErr; +} diff --git a/macosx/tkMacOSXUtil.h b/macosx/tkMacOSXUtil.h new file mode 100644 index 0000000..e38f8a5 --- /dev/null +++ b/macosx/tkMacOSXUtil.h @@ -0,0 +1,65 @@ +/* + * tkMacOSXUtil.h -- + * + * Declarations of utility functions from the MoreFiles package. + * + * FIXME: We should be able to replace all these with FSRef calls + * much more simply. + * + * Copyright 2001, Apple Computer, Inc. + * + * 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. + */ + +#ifndef TK_MAC_UTIL_H +#define TK_MAC_UTIL_H + +#include <Carbon/Carbon.h> + +OSErr FSpPathFromLocation(FSSpec *spec, int *length, Handle *fullPath); +OSErr FSpLocationFromPath(int length, const char *path, FSSpecPtr fileSpecPtr); +OSErr FSpGetDirectoryID(const FSSpec *spec, long *theDirID, Boolean *isDirectory); + +#endif diff --git a/macosx/tkMacOSXWindowEvent.c b/macosx/tkMacOSXWindowEvent.c new file mode 100644 index 0000000..d21d1f1 --- /dev/null +++ b/macosx/tkMacOSXWindowEvent.c @@ -0,0 +1,693 @@ +/* + * tkMacOSXWindowEvent.c -- + * + * This file defines the routines for both creating and handling + * Window Manager class events for Tk. + * + * Copyright 2001, Apple Computer, Inc. + * + * 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. + */ + +#include "tkMacOSXInt.h" +#include "tkPort.h" +#include "tkMacOSXWm.h" +#include "tkMacOSXEvent.h" +#include "tkMacOSXDebug.h" + +/* + * Declarations of global variables defined in this file. + */ + +int tkMacOSXAppInFront = true; /* Boolean variable for determining if + * we are the frontmost app. Only set + * in TkMacOSXProcessApplicationEvent + */ +static RgnHandle gDamageRgn; +static RgnHandle visRgn; + +/* + * Declaration of functions used only in this file + */ + +static int GenerateUpdateEvent( Window window); +static void GenerateUpdates( RgnHandle updateRgn, TkWindow *winPtr); +static int GenerateActivateEvents( Window window, int activeFlag); +static int GenerateFocusEvent( Window window, int activeFlag); + + + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXProcessApplicationEvent -- + * + * This processes Application level events, mainly activate + * and deactivate. + * + * Results: + * o. + * + * Side effects: + * Hide or reveal floating windows, and set tkMacOSXAppInFront. + * + *---------------------------------------------------------------------- + */ + +int +TkMacOSXProcessApplicationEvent( + TkMacOSXEvent *eventPtr, + MacEventStatus *statusPtr) +{ + statusPtr->handledByTk = 1; + switch (eventPtr->eKind) { + case kEventAppActivated: + tkMacOSXAppInFront = true; + ShowFloatingWindows(); + break; + case kEventAppDeactivated: + TkSuspendClipboard(); + tkMacOSXAppInFront = false; + HideFloatingWindows(); + break; + case kEventAppQuit: + case kEventAppLaunchNotification: + case kEventAppLaunched: + case kEventAppTerminated: + case kEventAppFrontSwitched: + break; + } + return 0; +} +/* + *---------------------------------------------------------------------- + * + * TkMacOSXProcessWindowEvent -- + * + * This processes Window level events, mainly activate + * and deactivate. + * + * Results: + * 0. + * + * Side effects: + * Cause Windows to be moved forward or backward in the + * window stack. + * + *---------------------------------------------------------------------- + */ + +int +TkMacOSXProcessWindowEvent( + TkMacOSXEvent * eventPtr, + MacEventStatus * statusPtr) +{ + OSStatus status; + WindowRef whichWindow; + Window window; + int eventFound; + + switch (eventPtr->eKind) { + case kEventWindowActivated: + case kEventWindowDeactivated: + case kEventWindowUpdate: + break; + default: + statusPtr->handledByTk = 1; + return 0; + break; + } + statusPtr->handledByTk = 1; + status = GetEventParameter(eventPtr->eventRef, + kEventParamDirectObject, + typeWindowRef, NULL, + sizeof(whichWindow), NULL, + &whichWindow); + if (status != noErr) { + fprintf ( stderr, "TkMacOSXHandleWindowEvent:Failed to retrieve window" ); + return 0; + } + + window = TkMacOSXGetXWindow(whichWindow); + + switch (eventPtr->eKind) { + case kEventWindowActivated: + eventFound |= GenerateActivateEvents(window, 1); + eventFound |= GenerateFocusEvent(window, 1); + break; + case kEventWindowDeactivated: + eventFound |= GenerateActivateEvents(window, 0); + eventFound |= GenerateFocusEvent(window, 0); + break; + case kEventWindowUpdate: + if (GenerateUpdateEvent(window)) { + eventFound = true; + } else { + statusPtr->handledByTk = 0; + } + break; + } + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * GenerateUpdateEvent -- + * + * Given a Macintosh window update event this function generates all the + * X update events needed by Tk. + * + * Results: + * True if event(s) are generated - false otherwise. + * + * Side effects: + * Additional events may be place on the Tk event queue. + * + *---------------------------------------------------------------------- + */ +static int +GenerateUpdateEvent(Window window) +{ + WindowRef macWindow; + TkDisplay * dispPtr; + TkWindow * winPtr; + Rect bounds; + + dispPtr = TkGetDisplayList(); + winPtr = (TkWindow *)Tk_IdToWindow(dispPtr->display, window); + + if (winPtr ==NULL ){ + return false; + } + if (gDamageRgn == NULL) { + gDamageRgn = NewRgn(); + } + if (visRgn == NULL) { + visRgn = NewRgn(); + } + macWindow = GetWindowFromPort(TkMacOSXGetDrawablePort(window)); + BeginUpdate(macWindow); + /* + * In the Classic version of the code, this was the "visRgn" field of the WindowRec + * This no longer exists in OS X, so retrieve the content region instead + * Note that this is in screen coordinates + * We therefore convert it to window relative coordinates + */ + GetWindowRegion (macWindow, kWindowContentRgn, visRgn ); + GetRegionBounds(visRgn,&bounds); + bounds.right -= bounds.left; + bounds.bottom -= bounds.top; + bounds.left= + bounds.top=0; + RectRgn(visRgn, &bounds); + GenerateUpdates(visRgn, winPtr); + EndUpdate(macWindow); + return true; + } + +/* + *---------------------------------------------------------------------- + * + * GenerateUpdates -- + * + * Given a Macintosh update region and a Tk window this function + * geneates a X damage event for the window if it is within the + * update region. The function will then recursivly have each + * damaged window generate damage events for its child windows. + * + * Results: + * None. + * + * Side effects: + * Additional events may be place on the Tk event queue. + * + *---------------------------------------------------------------------- + */ + +static void +GenerateUpdates( + RgnHandle updateRgn, + TkWindow *winPtr) +{ + TkWindow *childPtr; + XEvent event; + Rect bounds, updateBounds, damageBounds; + + TkMacOSXWinBounds(winPtr, &bounds); + GetRegionBounds(updateRgn,&updateBounds); + + if (bounds.top > updateBounds.bottom || + updateBounds.top > bounds.bottom || + bounds.left > updateBounds.right || + updateBounds.left > bounds.right || + !RectInRgn(&bounds, updateRgn)) { + return; + } + if (!RectInRgn(&bounds, updateRgn)) { + return; + } + + event.xany.serial = Tk_Display(winPtr)->request; + event.xany.send_event = false; + event.xany.window = Tk_WindowId(winPtr); + event.xany.display = Tk_Display(winPtr); + + event.type = Expose; + + /* + * Compute the bounding box of the area that the damage occured in. + */ + + /* + * CopyRgn(TkMacOSXVisableClipRgn(winPtr), rgn); + * TODO: this call doesn't work doing resizes!!! + */ + RectRgn(gDamageRgn, &bounds); + SectRgn(gDamageRgn, updateRgn, gDamageRgn); + OffsetRgn(gDamageRgn, -bounds.left, -bounds.top); + GetRegionBounds(gDamageRgn,&damageBounds); + event.xexpose.x = damageBounds.left; + event.xexpose.y = damageBounds.top; + event.xexpose.width = damageBounds.right-damageBounds.left; + event.xexpose.height = damageBounds.bottom-damageBounds.top; + event.xexpose.count = 0; + + Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); + + /* + * Generate updates for the children of this window + */ + + for (childPtr = winPtr->childList; childPtr != NULL; + childPtr = childPtr->nextPtr) { + if (!Tk_IsMapped(childPtr) || Tk_IsTopLevel(childPtr)) { + continue; + } + + GenerateUpdates(updateRgn, childPtr); + } + + /* + * Generate updates for any contained windows + */ + + if (Tk_IsContainer(winPtr)) { + childPtr = TkpGetOtherWindow(winPtr); + if (childPtr != NULL && Tk_IsMapped(childPtr)) { + GenerateUpdates(updateRgn, childPtr); + } + + /* + * NOTE: Here we should handle out of process embedding. + */ + + } + + return; +} + +/* + *---------------------------------------------------------------------- + * + * GenerateActivateEvents -- + * + * Given a Macintosh window activate event this function generates all the + * X Activate events needed by Tk. + * + * Results: + * True if event(s) are generated - false otherwise. + * + * Side effects: + * Additional events may be place on the Tk event queue. + * + *---------------------------------------------------------------------- + */ + +int +GenerateActivateEvents( + Window window, /* Root X window for event. */ + int activeFlag ) +{ + TkWindow *winPtr; + TkDisplay *dispPtr; + + dispPtr = TkGetDisplayList(); + winPtr = (TkWindow *) Tk_IdToWindow(dispPtr->display, window); + if (winPtr == NULL || winPtr->window == None) { + return false; + } + + TkGenerateActivateEvents(winPtr,activeFlag); + return true; +} + +/* + *---------------------------------------------------------------------- + * + * GenerateFocusEvent -- + * + * Given a Macintosh window activate event this function generates all the + * X Focus events needed by Tk. + * + * Results: + * True if event(s) are generated - false otherwise. + * + * Side effects: + * Additional events may be place on the Tk event queue. + * + *---------------------------------------------------------------------- + */ + +int +GenerateFocusEvent( + Window window, /* Root X window for event. */ + int activeFlag ) +{ + XEvent event; + Tk_Window tkwin; + TkDisplay *dispPtr; + + dispPtr = TkGetDisplayList(); + tkwin = Tk_IdToWindow(dispPtr->display, window); + if (tkwin == NULL) { + return false; + } + + /* + * Generate FocusIn and FocusOut events. This event + * is only sent to the toplevel window. + */ + + if (activeFlag) { + event.xany.type = FocusIn; + } else { + event.xany.type = FocusOut; + } + + event.xany.serial = dispPtr->display->request; + event.xany.send_event = False; + event.xfocus.display = dispPtr->display; + event.xfocus.window = window; + event.xfocus.mode = NotifyNormal; + event.xfocus.detail = NotifyDetailNone; + + Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); + return true; +} + +/* + *---------------------------------------------------------------------- + * + * TkGenWMConfigureEvent -- + * + * Generate a ConfigureNotify event for Tk. Depending on the + * value of flag the values of width/height, x/y, or both may + * be changed. + * + * Results: + * None. + * + * Side effects: + * A ConfigureNotify event is sent to Tk. + * + *---------------------------------------------------------------------- + */ + +void +TkGenWMConfigureEvent( + Tk_Window tkwin, + int x, + int y, + int width, + int height, + int flags) +{ + XEvent event; + WmInfo *wmPtr; + TkWindow *winPtr = (TkWindow *) tkwin; + + if (tkwin == NULL) { + return; + } + + event.type = ConfigureNotify; + event.xconfigure.serial = Tk_Display(tkwin)->request; + event.xconfigure.send_event = False; + event.xconfigure.display = Tk_Display(tkwin); + event.xconfigure.event = Tk_WindowId(tkwin); + event.xconfigure.window = Tk_WindowId(tkwin); + event.xconfigure.border_width = winPtr->changes.border_width; + event.xconfigure.override_redirect = winPtr->atts.override_redirect; + if (winPtr->changes.stack_mode == Above) { + event.xconfigure.above = winPtr->changes.sibling; + } else { + event.xconfigure.above = None; + } + + if (flags & TK_LOCATION_CHANGED) { + event.xconfigure.x = x; + event.xconfigure.y = y; + } else { + event.xconfigure.x = Tk_X(tkwin); + event.xconfigure.y = Tk_Y(tkwin); + x = Tk_X(tkwin); + y = Tk_Y(tkwin); + } + if (flags & TK_SIZE_CHANGED) { + event.xconfigure.width = width; + event.xconfigure.height = height; + } else { + event.xconfigure.width = Tk_Width(tkwin); + event.xconfigure.height = Tk_Height(tkwin); + width = Tk_Width(tkwin); + height = Tk_Height(tkwin); + } + + Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); + + /* + * Update window manager information. + */ + if (Tk_IsTopLevel(winPtr)) { + wmPtr = winPtr->wmInfoPtr; + if (flags & TK_LOCATION_CHANGED) { + wmPtr->x = x; + wmPtr->y = y; + wmPtr->flags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y); + } + if ((flags & TK_SIZE_CHANGED) && + ((width != Tk_Width(tkwin)) || (height != Tk_Height(tkwin)))) { + if ((wmPtr->width == -1) && (width == winPtr->reqWidth)) { + /* + * Don't set external width, since the user didn't change it + * from what the widgets asked for. + */ + } else { + if (wmPtr->gridWin != NULL) { + wmPtr->width = wmPtr->reqGridWidth + + (width - winPtr->reqWidth)/wmPtr->widthInc; + if (wmPtr->width < 0) { + wmPtr->width = 0; + } + } else { + wmPtr->width = width; + } + } + if ((wmPtr->height == -1) && (height == winPtr->reqHeight)) { + /* + * Don't set external height, since the user didn't change it + * from what the widgets asked for. + */ + } else { + if (wmPtr->gridWin != NULL) { + wmPtr->height = wmPtr->reqGridHeight + + (height - winPtr->reqHeight)/wmPtr->heightInc; + if (wmPtr->height < 0) { + wmPtr->height = 0; + } + } else { + wmPtr->height = height; + } + } + wmPtr->configWidth = width; + wmPtr->configHeight = height; + } + } + + /* + * Now set up the changes structure. Under X we wait for the + * ConfigureNotify to set these values. On the Mac we know imediatly that + * this is what we want - so we just set them. However, we need to + * make sure the windows clipping region is marked invalid so the + * change is visable to the subwindow. + */ + winPtr->changes.x = x; + winPtr->changes.y = y; + winPtr->changes.width = width; + winPtr->changes.height = height; + TkMacOSXInvalClipRgns(winPtr); +} + +/* + *---------------------------------------------------------------------- + * + * TkGenWMDestroyEvent -- + * + * Generate a WM Destroy event for Tk. * + * Results: + * None. + * + * Side effects: + * A WM_PROTOCOL/WM_DELETE_WINDOW event is sent to Tk. + * + *---------------------------------------------------------------------- + */ + +void +TkGenWMDestroyEvent( + Tk_Window tkwin) +{ + XEvent event; + + event.xany.serial = Tk_Display(tkwin)->request; + event.xany.send_event = False; + event.xany.display = Tk_Display(tkwin); + + event.xclient.window = Tk_WindowId(tkwin); + event.xclient.type = ClientMessage; + event.xclient.message_type = Tk_InternAtom(tkwin, "WM_PROTOCOLS"); + event.xclient.format = 32; + event.xclient.data.l[0] = Tk_InternAtom(tkwin, "WM_DELETE_WINDOW"); + Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL); +} + +/* + *---------------------------------------------------------------------- + * + * TkWmProtocolEventProc -- + * + * This procedure is called by the Tk_HandleEvent whenever a + * ClientMessage event arrives whose type is "WM_PROTOCOLS". + * This procedure handles the message from the window manager + * in an appropriate fashion. + * + * Results: + * None. + * + * Side effects: + * Depends on what sort of handler, if any, was set up for the + * protocol. + * + *---------------------------------------------------------------------- + */ + +void +TkWmProtocolEventProc( + TkWindow *winPtr, /* Window to which the event was sent. */ + XEvent *eventPtr) /* X event. */ +{ + WmInfo *wmPtr; + ProtocolHandler *protPtr; + Tcl_Interp *interp; + Atom protocol; + int result; + + wmPtr = winPtr->wmInfoPtr; + if (wmPtr == NULL) { + return; + } + protocol = (Atom) eventPtr->xclient.data.l[0]; + for (protPtr = wmPtr->protPtr; protPtr != NULL; + protPtr = protPtr->nextPtr) { + if (protocol == protPtr->protocol) { + Tcl_Preserve((ClientData) protPtr); + interp = protPtr->interp; + Tcl_Preserve((ClientData) interp); + result = Tcl_GlobalEval(interp, protPtr->command); + if (result != TCL_OK) { + Tcl_AddErrorInfo(interp, "\n (command for \""); + Tcl_AddErrorInfo(interp, + Tk_GetAtomName((Tk_Window) winPtr, protocol)); + Tcl_AddErrorInfo(interp, "\" window manager protocol)"); + Tk_BackgroundError(interp); + } + Tcl_Release((ClientData) interp); + Tcl_Release((ClientData) protPtr); + return; + } + } + + /* + * No handler was present for this protocol. If this is a + * WM_DELETE_WINDOW message then just destroy the window. + */ + + if (protocol == Tk_InternAtom((Tk_Window) winPtr, "WM_DELETE_WINDOW")) { + Tk_DestroyWindow((Tk_Window) winPtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * Tk_MacOSXIsAppInFront -- + * + * Returns 1 if this app is the foreground app. + * + * Results: + * 1 if app is in front, 0 otherwise. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +Tk_MacOSXIsAppInFront (void) +{ + return tkMacOSXAppInFront; +}
\ No newline at end of file diff --git a/macosx/tkMacOSXWm.c b/macosx/tkMacOSXWm.c new file mode 100644 index 0000000..094ef30 --- /dev/null +++ b/macosx/tkMacOSXWm.c @@ -0,0 +1,5506 @@ +/* + * tkMacOSXWm.c -- + * + * This module takes care of the interactions between a Tk-based + * application and the window manager. Among other things, it + * implements the "wm" command and passes geometry information + * to the window manager. + * + * Copyright (c) 1994-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkMacOSXWm.c,v 1.2 2002/08/31 06:12:30 das Exp $ + */ +#include <Carbon/Carbon.h> + +#include "tkPort.h" +#include "tkInt.h" +#include "tkMacOSXInt.h" +#include <errno.h> +#include "tkScrollbar.h" +#include "tkMacOSXWm.h" +#include "tkMacOSXEvent.h" +#include "tkMacOSXUtil.h" + +/* + * This is a list of all of the toplevels that have been mapped so far. It is + * used by the menu code to inval windows that were damaged by menus, and will + * eventually also be used to keep track of floating windows. + */ + +TkMacOSXWindowList *tkMacOSXWindowListPtr = NULL; + +/* + * The variable below is used to enable or disable tracing in this + * module. If tracing is enabled, then information is printed on + * standard output about interesting interactions with the window + * manager. + */ + +static int wmTracing = 0; + +/* + * The following structure is the official type record for geometry + * management of top-level windows. + */ + +static void TopLevelReqProc _ANSI_ARGS_((ClientData dummy, + Tk_Window tkwin)); + +static Tk_GeomMgr wmMgrType = { + "wm", /* name */ + TopLevelReqProc, /* requestProc */ + (Tk_GeomLostSlaveProc *) NULL, /* lostSlaveProc */ +}; + +/* + * Hash table for Mac Window -> TkWindow mapping. + */ + +static Tcl_HashTable windowTable; +static int windowHashInit = false; + +/* + * Forward declarations for procedures defined in this file: + */ + +static void InitialWindowBounds _ANSI_ARGS_((TkWindow *winPtr, + Rect *geometry)); +static int ParseGeometry _ANSI_ARGS_((Tcl_Interp *interp, + char *string, TkWindow *winPtr)); +static void TopLevelEventProc _ANSI_ARGS_((ClientData clientData, + XEvent *eventPtr)); +static void TopLevelReqProc _ANSI_ARGS_((ClientData dummy, + Tk_Window tkwin)); +static void UpdateGeometryInfo _ANSI_ARGS_(( + ClientData clientData)); +static void UpdateSizeHints _ANSI_ARGS_((TkWindow *winPtr)); +static void UpdateVRootGeometry _ANSI_ARGS_((WmInfo *wmPtr)); +static int WmAspectCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmAttributesCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmClientCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmColormapwindowsCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmCommandCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmDeiconifyCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmFocusmodelCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmFrameCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmGeometryCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmGridCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmGroupCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmIconbitmapCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmIconifyCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmIconmaskCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmIconnameCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmIconpositionCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmIconwindowCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmMaxsizeCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmMinsizeCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmOverrideredirectCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmPositionfromCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmProtocolCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmResizableCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmSizefromCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmStackorderCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmStateCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmTitleCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmTransientCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static int WmWithdrawCmd _ANSI_ARGS_((Tk_Window tkwin, + TkWindow *winPtr, Tcl_Interp *interp, int objc, + Tcl_Obj *CONST objv[])); +static void WmUpdateGeom _ANSI_ARGS_((WmInfo *wmPtr, + TkWindow *winPtr)); + +/* + *-------------------------------------------------------------- + * + * TkWmNewWindow -- + * + * This procedure is invoked whenever a new top-level + * window is created. Its job is to initialize the WmInfo + * structure for the window. + * + * Results: + * None. + * + * Side effects: + * A WmInfo structure gets allocated and initialized. + * + *-------------------------------------------------------------- + */ + +void +TkWmNewWindow( + TkWindow *winPtr) /* Newly-created top-level window. */ +{ + WmInfo *wmPtr; + + wmPtr = (WmInfo *) ckalloc(sizeof(WmInfo)); + wmPtr->winPtr = winPtr; + wmPtr->reparent = None; + wmPtr->titleUid = NULL; + wmPtr->iconName = NULL; + wmPtr->master = None; + wmPtr->hints.flags = InputHint | StateHint; + wmPtr->hints.input = True; + wmPtr->hints.initial_state = NormalState; + wmPtr->hints.icon_pixmap = None; + wmPtr->hints.icon_window = None; + wmPtr->hints.icon_x = wmPtr->hints.icon_y = 0; + wmPtr->hints.icon_mask = None; + wmPtr->hints.window_group = None; + wmPtr->leaderName = NULL; + wmPtr->masterWindowName = NULL; + wmPtr->icon = NULL; + wmPtr->iconFor = NULL; + wmPtr->sizeHintsFlags = 0; + wmPtr->minWidth = wmPtr->minHeight = 1; + + /* + * Default the maximum dimensions to the size of the display, minus + * a guess about how space is needed for window manager decorations. + */ + + wmPtr->maxWidth = DisplayWidth(winPtr->display, winPtr->screenNum) - 15; + wmPtr->maxHeight = DisplayHeight(winPtr->display, winPtr->screenNum) - 30; + wmPtr->gridWin = NULL; + wmPtr->widthInc = wmPtr->heightInc = 1; + wmPtr->minAspect.x = wmPtr->minAspect.y = 1; + wmPtr->maxAspect.x = wmPtr->maxAspect.y = 1; + wmPtr->reqGridWidth = wmPtr->reqGridHeight = -1; + wmPtr->gravity = NorthWestGravity; + wmPtr->width = -1; + wmPtr->height = -1; + wmPtr->x = winPtr->changes.x; + wmPtr->y = winPtr->changes.y; + wmPtr->parentWidth = winPtr->changes.width + + 2*winPtr->changes.border_width; + wmPtr->parentHeight = winPtr->changes.height + + 2*winPtr->changes.border_width; + wmPtr->xInParent = 0; + wmPtr->yInParent = 0; + wmPtr->cmapList = NULL; + wmPtr->cmapCount = 0; + wmPtr->configWidth = -1; + wmPtr->configHeight = -1; + wmPtr->vRoot = None; + wmPtr->protPtr = NULL; + wmPtr->cmdArgv = NULL; + wmPtr->clientMachine = NULL; + wmPtr->flags = WM_NEVER_MAPPED; + wmPtr->style = -1; + wmPtr->macClass = kDocumentWindowClass; + wmPtr->attributes = kWindowStandardDocumentAttributes; + wmPtr->scrollWinPtr = NULL; + winPtr->wmInfoPtr = wmPtr; + + UpdateVRootGeometry(wmPtr); + + /* + * Tk must monitor structure events for top-level windows, in order + * to detect size and position changes caused by window managers. + */ + + Tk_CreateEventHandler((Tk_Window) winPtr, StructureNotifyMask, + TopLevelEventProc, (ClientData) winPtr); + + /* + * Arrange for geometry requests to be reflected from the window + * to the window manager. + */ + + Tk_ManageGeometry((Tk_Window) winPtr, &wmMgrType, (ClientData) 0); +} + +/* + *-------------------------------------------------------------- + * + * TkWmMapWindow -- + * + * This procedure is invoked to map a top-level window. This + * module gets a chance to update all window-manager-related + * information in properties before the window manager sees + * the map event and checks the properties. It also gets to + * decide whether or not to even map the window after all. + * + * Results: + * None. + * + * Side effects: + * Properties of winPtr may get updated to provide up-to-date + * information to the window manager. The window may also get + * mapped, but it may not be if this procedure decides that + * isn't appropriate (e.g. because the window is withdrawn). + * + *-------------------------------------------------------------- + */ + +void +TkWmMapWindow( + TkWindow *winPtr) /* Top-level window that's about to + * be mapped. */ +{ + WmInfo *wmPtr = winPtr->wmInfoPtr; + Point where = {0, 0}; + int xOffset, yOffset; + int firstMap = false; + MacDrawable *macWin; + + if (wmPtr->flags & WM_NEVER_MAPPED) { + wmPtr->flags &= ~WM_NEVER_MAPPED; + firstMap = true; + + /* + * Create the underlying Mac window for this Tk window. + */ + macWin = (MacDrawable *) winPtr->window; + if (!TkMacOSXHostToplevelExists(winPtr)) { + TkMacOSXMakeRealWindowExist(winPtr); + } + + /* + * Generate configure event when we first map the window. + */ + LocalToGlobal(&where); + TkMacOSXWindowOffset( GetWindowFromPort(TkMacOSXGetDrawablePort((Drawable) macWin)), + &xOffset, &yOffset); + where.h -= xOffset; + where.v -= yOffset; + TkGenWMConfigureEvent((Tk_Window) winPtr, + where.h, where.v, -1, -1, TK_LOCATION_CHANGED); + + /* + * This is the first time this window has ever been mapped. + * Store all the window-manager-related information for the + * window. + */ + + if (wmPtr->titleUid == NULL) { + wmPtr->titleUid = winPtr->nameUid; + } + + if (!Tk_IsEmbedded(winPtr)) { + TkSetWMName(winPtr, wmPtr->titleUid); + } + + TkWmSetClass(winPtr); + + if (wmPtr->iconName != NULL) { + XSetIconName(winPtr->display, winPtr->window, wmPtr->iconName); + } + + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + } + if (wmPtr->hints.initial_state == WithdrawnState) { + return; + } + + /* + * TODO: we need to display a window if it's iconic on creation. + */ + + if (wmPtr->hints.initial_state == IconicState) { + return; + } + + /* + * Update geometry information. + */ + wmPtr->flags |= WM_ABOUT_TO_MAP; + if (wmPtr->flags & WM_UPDATE_PENDING) { + Tk_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr); + } + UpdateGeometryInfo((ClientData) winPtr); + wmPtr->flags &= ~WM_ABOUT_TO_MAP; + + /* + * Map the window. + */ + + XMapWindow(winPtr->display, winPtr->window); + + /* + * Now that the window is visable we can determine the offset + * from the window's content orgin to the window's decorative + * orgin (structure orgin). + */ + TkMacOSXWindowOffset( GetWindowFromPort(TkMacOSXGetDrawablePort(Tk_WindowId(winPtr))), + &wmPtr->xInParent, &wmPtr->yInParent); +} + +/* + *-------------------------------------------------------------- + * + * TkWmUnmapWindow -- + * + * This procedure is invoked to unmap a top-level window. + * On the Macintosh all we do is call XUnmapWindow. + * + * Results: + * None. + * + * Side effects: + * Unmaps the window. + * + *-------------------------------------------------------------- + */ + +void +TkWmUnmapWindow( + TkWindow *winPtr) /* Top-level window that's about to + * be mapped. */ +{ + XUnmapWindow(winPtr->display, winPtr->window); +} + +/* + *-------------------------------------------------------------- + * + * TkWmDeadWindow -- + * + * This procedure is invoked when a top-level window is + * about to be deleted. It cleans up the wm-related data + * structures for the window. + * + * Results: + * None. + * + * Side effects: + * The WmInfo structure for winPtr gets freed up. + * + *-------------------------------------------------------------- + */ + +void +TkWmDeadWindow(winPtr) + TkWindow *winPtr; /* Top-level window that's being deleted. */ +{ + WmInfo *wmPtr = winPtr->wmInfoPtr; + WmInfo *wmPtr2; + + if (wmPtr == NULL) { + return; + } + if (wmPtr->hints.flags & IconPixmapHint) { + Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap); + } + if (wmPtr->hints.flags & IconMaskHint) { + Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask); + } + if (wmPtr->leaderName != NULL) { + ckfree(wmPtr->leaderName); + } + if (wmPtr->masterWindowName != NULL) { + ckfree(wmPtr->masterWindowName); + } + if (wmPtr->icon != NULL) { + wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr; + wmPtr2->iconFor = NULL; + } + if (wmPtr->iconFor != NULL) { + wmPtr2 = ((TkWindow *) wmPtr->iconFor)->wmInfoPtr; + wmPtr2->icon = NULL; + wmPtr2->hints.flags &= ~IconWindowHint; + } + while (wmPtr->protPtr != NULL) { + ProtocolHandler *protPtr; + + protPtr = wmPtr->protPtr; + wmPtr->protPtr = protPtr->nextPtr; + Tcl_EventuallyFree((ClientData) protPtr, TCL_DYNAMIC); + } + if (wmPtr->cmdArgv != NULL) { + ckfree((char *) wmPtr->cmdArgv); + } + if (wmPtr->clientMachine != NULL) { + ckfree((char *) wmPtr->clientMachine); + } + if (wmPtr->flags & WM_UPDATE_PENDING) { + Tk_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr); + } + ckfree((char *) wmPtr); + winPtr->wmInfoPtr = NULL; +} + +/* + *-------------------------------------------------------------- + * + * TkWmSetClass -- + * + * This procedure is invoked whenever a top-level window's + * class is changed. If the window has been mapped then this + * procedure updates the window manager property for the + * class. If the window hasn't been mapped, the update is + * deferred until just before the first mapping. + * + * Results: + * None. + * + * Side effects: + * A window property may get updated. + * + *-------------------------------------------------------------- + */ + +void +TkWmSetClass( + TkWindow *winPtr) /* Newly-created top-level window. */ +{ + return; +} +/* + *---------------------------------------------------------------------- + * + * Tk_WmObjCmd -- + * + * This procedure is invoked to process the "wm" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +/* ARGSUSED */ +int +Tk_WmObjCmd( + 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; + static CONST char *optionStrings[] = { + "aspect", "attributes", "client", "colormapwindows", + "command", "deiconify", "focusmodel", "frame", + "geometry", "grid", "group", "iconbitmap", + "iconify", "iconmask", "iconname", "iconposition", + "iconwindow", "maxsize", "minsize", "overrideredirect", + "positionfrom", "protocol", "resizable", "sizefrom", + "stackorder", "state", "title", "transient", + "withdraw", (char *) NULL }; + enum options { + WMOPT_ASPECT, WMOPT_ATTRIBUTES, WMOPT_CLIENT, WMOPT_COLORMAPWINDOWS, + WMOPT_COMMAND, WMOPT_DEICONIFY, WMOPT_FOCUSMODEL, WMOPT_FRAME, + WMOPT_GEOMETRY, WMOPT_GRID, WMOPT_GROUP, WMOPT_ICONBITMAP, + WMOPT_ICONIFY, WMOPT_ICONMASK, WMOPT_ICONNAME, WMOPT_ICONPOSITION, + WMOPT_ICONWINDOW, WMOPT_MAXSIZE, WMOPT_MINSIZE, WMOPT_OVERRIDEREDIRECT, + WMOPT_POSITIONFROM, WMOPT_PROTOCOL, WMOPT_RESIZABLE, WMOPT_SIZEFROM, + WMOPT_STACKORDER, WMOPT_STATE, WMOPT_TITLE, WMOPT_TRANSIENT, + WMOPT_WITHDRAW }; + int index, length; + char *argv1; + TkWindow *winPtr; + + if (objc < 2) { +wrongNumArgs: + Tcl_WrongNumArgs(interp, 1, objv, "option window ?arg ...?"); + return TCL_ERROR; + } + + argv1 = Tcl_GetStringFromObj(objv[1], &length); + if ((argv1[0] == 't') && (strncmp(argv1, "tracing", length) == 0) + && (length >= 3)) { + if ((objc != 2) && (objc != 3)) { + Tcl_WrongNumArgs(interp, 2, objv, "?boolean?"); + return TCL_ERROR; + } + if (objc == 2) { + Tcl_SetResult(interp, ((wmTracing) ? "on" : "off"), TCL_STATIC); + return TCL_OK; + } + return Tcl_GetBooleanFromObj(interp, objv[2], &wmTracing); + } + + if (Tcl_GetIndexFromObj(interp, objv[1], optionStrings, "option", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + + if (objc < 3) { + goto wrongNumArgs; + } + + if (TkGetWindowFromObj(interp, tkwin, objv[2], (Tk_Window *) &winPtr) + != TCL_OK) { + return TCL_ERROR; + } + if (!Tk_IsTopLevel(winPtr)) { + Tcl_AppendResult(interp, "window \"", winPtr->pathName, + "\" isn't a top-level window", (char *) NULL); + return TCL_ERROR; + } + + switch ((enum options) index) { + case WMOPT_ASPECT: + return WmAspectCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ATTRIBUTES: + return WmAttributesCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_CLIENT: + return WmClientCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_COLORMAPWINDOWS: + return WmColormapwindowsCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_COMMAND: + return WmCommandCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_DEICONIFY: + return WmDeiconifyCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_FOCUSMODEL: + return WmFocusmodelCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_FRAME: + return WmFrameCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_GEOMETRY: + return WmGeometryCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_GRID: + return WmGridCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_GROUP: + return WmGroupCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONBITMAP: + return WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONIFY: + return WmIconifyCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONMASK: + return WmIconmaskCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONNAME: + return WmIconnameCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONPOSITION: + return WmIconpositionCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_ICONWINDOW: + return WmIconwindowCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_MAXSIZE: + return WmMaxsizeCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_MINSIZE: + return WmMinsizeCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_OVERRIDEREDIRECT: + return WmOverrideredirectCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_POSITIONFROM: + return WmPositionfromCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_PROTOCOL: + return WmProtocolCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_RESIZABLE: + return WmResizableCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_SIZEFROM: + return WmSizefromCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_STACKORDER: + return WmStackorderCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_STATE: + return WmStateCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_TITLE: + return WmTitleCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_TRANSIENT: + return WmTransientCmd(tkwin, winPtr, interp, objc, objv); + case WMOPT_WITHDRAW: + return WmWithdrawCmd(tkwin, winPtr, interp, objc, objv); + } + + /* This should not happen */ + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * + * WmAspectCmd -- + * + * This procedure is invoked to process the "wm aspect" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmAspectCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int numer1, denom1, numer2, denom2; + + if ((objc != 3) && (objc != 7)) { + Tcl_WrongNumArgs(interp, 2, objv, + "window ?minNumer minDenom maxNumer maxDenom?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->sizeHintsFlags & PAspect) { + char buf[TCL_INTEGER_SPACE * 4]; + + sprintf(buf, "%d %d %d %d", wmPtr->minAspect.x, + wmPtr->minAspect.y, wmPtr->maxAspect.x, + wmPtr->maxAspect.y); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + } + return TCL_OK; + } + if (*Tcl_GetString(objv[3]) == '\0') { + wmPtr->sizeHintsFlags &= ~PAspect; + } else { + if ((Tcl_GetIntFromObj(interp, objv[3], &numer1) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[4], &denom1) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[5], &numer2) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[6], &denom2) != TCL_OK)) { + return TCL_ERROR; + } + if ((numer1 <= 0) || (denom1 <= 0) || (numer2 <= 0) || + (denom2 <= 0)) { + Tcl_SetResult(interp, "aspect number can't be <= 0", + TCL_STATIC); + return TCL_ERROR; + } + wmPtr->minAspect.x = numer1; + wmPtr->minAspect.y = denom1; + wmPtr->maxAspect.x = numer2; + wmPtr->maxAspect.y = denom2; + wmPtr->sizeHintsFlags |= PAspect; + } + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmAttributesCmd -- + * + * This procedure is invoked to process the "wm attributes" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmAttributesCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + char buf[TCL_INTEGER_SPACE]; + int i; + WindowRef macWindow; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "window"); + return TCL_ERROR; + } + if (objc < 3) { +configArgs: + Tcl_AppendResult(interp, "wrong # arguments: must be \"", + Tcl_GetStringFromObj (objv[0], NULL), " attributes window", + " ?-modified ?bool??", + "\"", (char *) NULL); + return TCL_ERROR; + } + macWindow = GetWindowFromPort(TkMacOSXGetDrawablePort(winPtr->window)); + if (objc == 3) { + FSSpec spec; + sprintf(buf, "%d", (IsWindowModified(macWindow) == true)); + Tcl_AppendResult(interp, "-modified ", buf, (char *) NULL); + if (GetWindowProxyFSSpec(macWindow, &spec) == noErr) { + Tcl_AppendResult(interp, " -titlepath", (char *) NULL); + /* Need to get the path from the spec */ + Tcl_AppendElement(interp, "<read_unimplemented>"); + } else { + Tcl_AppendResult(interp, " -titlepath {}", (char *) NULL); + } + return TCL_OK; + } + for (i = 3; i < objc; i += 2) { + int length; + char *argPtr = Tcl_GetStringFromObj(objv[i], &length); + if ((length < 2) || (*argPtr != '-')) { + goto configArgs; + } + if (strncmp(argPtr, "-modified", length) == 0) { + int boolean; + if (i < objc - 1) { + if (Tcl_GetBooleanFromObj(interp, objv[i+1], &boolean) != TCL_OK) { + return TCL_ERROR; + } + SetWindowModified(macWindow, boolean); + } + } else if (strncmp(argPtr, "-titlepath", length) == 0) { + if (i < objc - 1) { + OSErr err; + FSSpec spec; + FSRef ref; + Boolean isDirectory; + err = FSPathMakeRef(Tcl_GetStringFromObj(objv[i+1], NULL), &ref, &isDirectory); + if (err == noErr) { + err = FSGetCatalogInfo(&ref, kFSCatInfoNone, NULL, NULL, + &spec, NULL); + if (err == noErr) { + if (SetWindowProxyFSSpec(macWindow,&spec) != noErr) { + Tcl_AppendResult(interp, "couldn't set window proxy title path", + (char *) NULL); + return TCL_ERROR; + } + } + } + } + } else { + goto configArgs; + } + if (i == objc - 2) { + /* Want to return last result */ + Tcl_SetObjResult(interp, objv[i+1]); + } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmClientCmd -- + * + * This procedure is invoked to process the "wm client" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmClientCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + char *argv3; + int length; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?name?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->clientMachine != NULL) { + Tcl_SetResult(interp, wmPtr->clientMachine, TCL_STATIC); + } + return TCL_OK; + } + argv3 = Tcl_GetStringFromObj(objv[3], &length); + if (argv3[0] == 0) { + if (wmPtr->clientMachine != NULL) { + ckfree((char *) wmPtr->clientMachine); + wmPtr->clientMachine = NULL; + } + return TCL_OK; + } + if (wmPtr->clientMachine != NULL) { + ckfree((char *) wmPtr->clientMachine); + } + wmPtr->clientMachine = (char *) + ckalloc((unsigned) (length + 1)); + strcpy(wmPtr->clientMachine, argv3); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmColormapwindowsCmd -- + * + * This procedure is invoked to process the "wm colormapwindows" + * Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmColormapwindowsCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + TkWindow **cmapList; + TkWindow *winPtr2; + int i, windowObjc, gotToplevel = 0; + Tcl_Obj **windowObjv; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?windowList?"); + return TCL_ERROR; + } + if (objc == 3) { + Tk_MakeWindowExist((Tk_Window) winPtr); + for (i = 0; i < wmPtr->cmapCount; i++) { + if ((i == (wmPtr->cmapCount-1)) + && (wmPtr->flags & WM_ADDED_TOPLEVEL_COLORMAP)) { + break; + } + Tcl_AppendElement(interp, wmPtr->cmapList[i]->pathName); + } + return TCL_OK; + } + if (Tcl_ListObjGetElements(interp, objv[3], &windowObjc, &windowObjv) + != TCL_OK) { + return TCL_ERROR; + } + cmapList = (TkWindow **) ckalloc((unsigned) + ((windowObjc+1)*sizeof(TkWindow*))); + for (i = 0; i < windowObjc; i++) { + if (TkGetWindowFromObj(interp, tkwin, windowObjv[i], + (Tk_Window *) &winPtr2) != TCL_OK) + { + ckfree((char *) cmapList); + return TCL_ERROR; + } + if (winPtr2 == winPtr) { + gotToplevel = 1; + } + if (winPtr2->window == None) { + Tk_MakeWindowExist((Tk_Window) winPtr2); + } + cmapList[i] = winPtr2; + } + if (!gotToplevel) { + wmPtr->flags |= WM_ADDED_TOPLEVEL_COLORMAP; + cmapList[windowObjc] = winPtr; + windowObjc++; + } else { + wmPtr->flags &= ~WM_ADDED_TOPLEVEL_COLORMAP; + } + wmPtr->flags |= WM_COLORMAPS_EXPLICIT; + if (wmPtr->cmapList != NULL) { + ckfree((char *)wmPtr->cmapList); + } + wmPtr->cmapList = cmapList; + wmPtr->cmapCount = windowObjc; + + /* + * On the Macintosh all of this is just an excercise + * in compatability as we don't support colormaps. If + * we did they would be installed here. + */ + + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmCommandCmd -- + * + * This procedure is invoked to process the "wm command" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmCommandCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + char *argv3; + int cmdArgc; + CONST char **cmdArgv; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?value?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->cmdArgv != NULL) { + Tcl_SetResult(interp, + Tcl_Merge(wmPtr->cmdArgc, wmPtr->cmdArgv), + TCL_DYNAMIC); + } + return TCL_OK; + } + argv3 = Tcl_GetString(objv[3]); + if (argv3[0] == 0) { + if (wmPtr->cmdArgv != NULL) { + ckfree((char *) wmPtr->cmdArgv); + wmPtr->cmdArgv = NULL; + } + return TCL_OK; + } + if (Tcl_SplitList(interp, argv3, &cmdArgc, &cmdArgv) != TCL_OK) { + return TCL_ERROR; + } + if (wmPtr->cmdArgv != NULL) { + ckfree((char *) wmPtr->cmdArgv); + } + wmPtr->cmdArgc = cmdArgc; + wmPtr->cmdArgv = cmdArgv; + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmDeiconifyCmd -- + * + * This procedure is invoked to process the "wm deiconify" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmDeiconifyCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "window"); + return TCL_ERROR; + } + if (wmPtr->iconFor != NULL) { + Tcl_AppendResult(interp, "can't deiconify ", Tcl_GetString(objv[2]), + ": it is an icon for ", Tk_PathName(wmPtr->iconFor), + (char *) NULL); + return TCL_ERROR; + } + if (winPtr->flags & TK_EMBEDDED) { + Tcl_AppendResult(interp, "can't deiconify ", winPtr->pathName, + ": it is an embedded window", (char *) NULL); + return TCL_ERROR; + } + + /* + * TODO: may not want to call this function - look at Map events gened. + */ + + TkpWmSetState(winPtr, NormalState); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmFocusmodelCmd -- + * + * This procedure is invoked to process the "wm focusmodel" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmFocusmodelCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + static CONST char *optionStrings[] = { + "active", "passive", (char *) NULL }; + enum options { + OPT_ACTIVE, OPT_PASSIVE }; + int index; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?active|passive?"); + return TCL_ERROR; + } + if (objc == 3) { + Tcl_SetResult(interp, (wmPtr->hints.input ? "passive" : "active"), + TCL_STATIC); + return TCL_OK; + } + + if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + if (index == OPT_ACTIVE) { + wmPtr->hints.input = False; + } else { /* OPT_PASSIVE */ + wmPtr->hints.input = True; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmFrameCmd -- + * + * This procedure is invoked to process the "wm frame" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmFrameCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + Window window; + char buf[TCL_INTEGER_SPACE]; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "window"); + return TCL_ERROR; + } + window = wmPtr->reparent; + if (window == None) { + window = Tk_WindowId((Tk_Window) winPtr); + } + sprintf(buf, "0x%x", (unsigned int) window); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmGeometryCmd -- + * + * This procedure is invoked to process the "wm geometry" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmGeometryCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + char xSign, ySign; + int width, height; + char *argv3; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?newGeometry?"); + return TCL_ERROR; + } + if (objc == 3) { + char buf[16 + TCL_INTEGER_SPACE * 4]; + + xSign = (wmPtr->flags & WM_NEGATIVE_X) ? '-' : '+'; + ySign = (wmPtr->flags & WM_NEGATIVE_Y) ? '-' : '+'; + if (wmPtr->gridWin != NULL) { + width = wmPtr->reqGridWidth + (winPtr->changes.width + - winPtr->reqWidth)/wmPtr->widthInc; + height = wmPtr->reqGridHeight + (winPtr->changes.height + - winPtr->reqHeight)/wmPtr->heightInc; + } else { + width = winPtr->changes.width; + height = winPtr->changes.height; + } + sprintf(buf, "%dx%d%c%d%c%d", width, height, xSign, wmPtr->x, + ySign, wmPtr->y); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + return TCL_OK; + } + argv3 = Tcl_GetString(objv[3]); + if (*argv3 == '\0') { + wmPtr->width = -1; + wmPtr->height = -1; + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; + } + return ParseGeometry(interp, argv3, winPtr); +} + +/* + *---------------------------------------------------------------------- + * + * WmGridCmd -- + * + * This procedure is invoked to process the "wm grid" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmGridCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int reqWidth, reqHeight, widthInc, heightInc; + + if ((objc != 3) && (objc != 7)) { + Tcl_WrongNumArgs(interp, 2, objv, + "window ?baseWidth baseHeight widthInc heightInc?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->sizeHintsFlags & PBaseSize) { + char buf[TCL_INTEGER_SPACE * 4]; + + sprintf(buf, "%d %d %d %d", wmPtr->reqGridWidth, + wmPtr->reqGridHeight, wmPtr->widthInc, + wmPtr->heightInc); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + } + return TCL_OK; + } + if (*Tcl_GetString(objv[3]) == '\0') { + /* + * Turn off gridding and reset the width and height + * to make sense as ungridded numbers. + */ + + wmPtr->sizeHintsFlags &= ~(PBaseSize|PResizeInc); + if (wmPtr->width != -1) { + wmPtr->width = winPtr->reqWidth + (wmPtr->width + - wmPtr->reqGridWidth)*wmPtr->widthInc; + wmPtr->height = winPtr->reqHeight + (wmPtr->height + - wmPtr->reqGridHeight)*wmPtr->heightInc; + } + wmPtr->widthInc = 1; + wmPtr->heightInc = 1; + } else { + if ((Tcl_GetIntFromObj(interp, objv[3], &reqWidth) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[4], &reqHeight) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[5], &widthInc) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[6], &heightInc) != TCL_OK)) { + return TCL_ERROR; + } + if (reqWidth < 0) { + Tcl_SetResult(interp, "baseWidth can't be < 0", TCL_STATIC); + return TCL_ERROR; + } + if (reqHeight < 0) { + Tcl_SetResult(interp, "baseHeight can't be < 0", TCL_STATIC); + return TCL_ERROR; + } + if (widthInc < 0) { + Tcl_SetResult(interp, "widthInc can't be < 0", TCL_STATIC); + return TCL_ERROR; + } + if (heightInc < 0) { + Tcl_SetResult(interp, "heightInc can't be < 0", TCL_STATIC); + return TCL_ERROR; + } + Tk_SetGrid((Tk_Window) winPtr, reqWidth, reqHeight, widthInc, + heightInc); + } + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmGroupCmd -- + * + * This procedure is invoked to process the "wm group" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmGroupCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + Tk_Window tkwin2; + char *argv3; + int length; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?pathName?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->hints.flags & WindowGroupHint) { + Tcl_SetResult(interp, wmPtr->leaderName, TCL_STATIC); + } + return TCL_OK; + } + argv3 = Tcl_GetStringFromObj(objv[3], &length); + if (*argv3 == '\0') { + wmPtr->hints.flags &= ~WindowGroupHint; + if (wmPtr->leaderName != NULL) { + ckfree(wmPtr->leaderName); + } + wmPtr->leaderName = NULL; + } else { + if (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) { + return TCL_ERROR; + } + Tk_MakeWindowExist(tkwin2); + if (wmPtr->leaderName != NULL) { + ckfree(wmPtr->leaderName); + } + wmPtr->hints.window_group = Tk_WindowId(tkwin2); + wmPtr->hints.flags |= WindowGroupHint; + wmPtr->leaderName = ckalloc((unsigned) (length + 1)); + strcpy(wmPtr->leaderName, argv3); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmIconbitmapCmd -- + * + * This procedure is invoked to process the "wm iconbitmap" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + char *argv3; + Pixmap pixmap; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?bitmap?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->hints.flags & IconPixmapHint) { + Tcl_SetResult(interp, + (char *) Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_pixmap), + TCL_STATIC); + } + return TCL_OK; + } + argv3 = Tcl_GetString(objv[3]); + if (*argv3 == '\0') { + if (wmPtr->hints.icon_pixmap != None) { + Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_pixmap); + wmPtr->hints.icon_pixmap = None; + } + wmPtr->hints.flags &= ~IconPixmapHint; + } else { + OSErr err; + FSSpec spec; + FSRef ref; + Boolean isDirectory; + err = FSPathMakeRef(Tcl_GetStringFromObj(objv[3], NULL), &ref, &isDirectory); + if (err == noErr) { + err = FSGetCatalogInfo (&ref, kFSCatInfoNone, NULL, NULL, &spec, NULL); + if (err == noErr) { + WindowRef macWin + = GetWindowFromPort(TkMacOSXGetDrawablePort(winPtr->window)); + SetWindowProxyFSSpec(macWin, &spec); + return TCL_OK; + } + } + pixmap = Tk_GetBitmap(interp, (Tk_Window) winPtr, + Tk_GetUid(Tcl_GetStringFromObj(objv[3], NULL))); + if (pixmap == None) { + return TCL_ERROR; + } + wmPtr->hints.icon_pixmap = pixmap; + wmPtr->hints.flags |= IconPixmapHint; + } + + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmIconifyCmd -- + * + * This procedure is invoked to process the "wm iconify" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmIconifyCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "window"); + return TCL_ERROR; + } + if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) { + Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName, + "\": override-redirect flag is set", (char *) NULL); + return TCL_ERROR; + } + if (wmPtr->master != None) { + Tcl_AppendResult(interp, "can't iconify \"", winPtr->pathName, + "\": it is a transient", (char *) NULL); + return TCL_ERROR; + } + if (wmPtr->iconFor != NULL) { + Tcl_AppendResult(interp, "can't iconify ", winPtr->pathName, + ": it is an icon for ", Tk_PathName(wmPtr->iconFor), + (char *) NULL); + return TCL_ERROR; + } + if (winPtr->flags & TK_EMBEDDED) { + Tcl_AppendResult(interp, "can't iconify ", winPtr->pathName, + ": it is an embedded window", (char *) NULL); + return TCL_ERROR; + } + TkpWmSetState(winPtr, IconicState); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmIconmaskCmd -- + * + * This procedure is invoked to process the "wm iconmask" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmIconmaskCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + Pixmap pixmap; + char *argv3; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?bitmap?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->hints.flags & IconMaskHint) { + Tcl_SetResult(interp, + (char *) Tk_NameOfBitmap(winPtr->display, wmPtr->hints.icon_mask), + TCL_STATIC); + } + return TCL_OK; + } + argv3 = Tcl_GetString(objv[3]); + if (*argv3 == '\0') { + if (wmPtr->hints.icon_mask != None) { + Tk_FreeBitmap(winPtr->display, wmPtr->hints.icon_mask); + } + wmPtr->hints.flags &= ~IconMaskHint; + } else { + pixmap = Tk_GetBitmap(interp, tkwin, argv3); + if (pixmap == None) { + return TCL_ERROR; + } + wmPtr->hints.icon_mask = pixmap; + wmPtr->hints.flags |= IconMaskHint; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmIconnameCmd -- + * + * This procedure is invoked to process the "wm iconname" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmIconnameCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + CONST char *argv3; + int length; + + if (objc > 4) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?newName?"); + return TCL_ERROR; + } + if (objc == 3) { + Tcl_SetResult(interp, + (char *) ((wmPtr->iconName != NULL) ? wmPtr->iconName : ""), + TCL_STATIC); + return TCL_OK; + } else { + if (wmPtr->iconName != NULL) { + ckfree((char *) wmPtr->iconName); + } + argv3 = Tcl_GetStringFromObj(objv[3], &length); + wmPtr->iconName = ckalloc((unsigned) (length + 1)); + strcpy(wmPtr->iconName, argv3); + if (!(wmPtr->flags & WM_NEVER_MAPPED)) { + XSetIconName(winPtr->display, winPtr->window, wmPtr->iconName); + } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmIconpositionCmd -- + * + * This procedure is invoked to process the "wm iconposition" + * Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmIconpositionCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int x, y; + + if ((objc != 3) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?x y?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->hints.flags & IconPositionHint) { + char buf[TCL_INTEGER_SPACE * 2]; + + sprintf(buf, "%d %d", wmPtr->hints.icon_x, + wmPtr->hints.icon_y); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + } + return TCL_OK; + } + if (*Tcl_GetString(objv[3]) == '\0') { + wmPtr->hints.flags &= ~IconPositionHint; + } else { + if ((Tcl_GetIntFromObj(interp, objv[3], &x) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[4], &y) != TCL_OK)){ + return TCL_ERROR; + } + wmPtr->hints.icon_x = x; + wmPtr->hints.icon_y = y; + wmPtr->hints.flags |= IconPositionHint; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmIconwindowCmd -- + * + * This procedure is invoked to process the "wm iconwindow" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmIconwindowCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + Tk_Window tkwin2; + WmInfo *wmPtr2; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?pathName?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->icon != NULL) { + Tcl_SetResult(interp, Tk_PathName(wmPtr->icon), TCL_STATIC); + } + return TCL_OK; + } + if (*Tcl_GetString(objv[3]) == '\0') { + wmPtr->hints.flags &= ~IconWindowHint; + if (wmPtr->icon != NULL) { + wmPtr2 = ((TkWindow *) wmPtr->icon)->wmInfoPtr; + wmPtr2->iconFor = NULL; + wmPtr2->hints.initial_state = WithdrawnState; + } + wmPtr->icon = NULL; + } else { + if (TkGetWindowFromObj(interp, tkwin, objv[3], &tkwin2) != TCL_OK) { + return TCL_ERROR; + } + if (!Tk_IsTopLevel(tkwin2)) { + Tcl_AppendResult(interp, "can't use ", Tcl_GetString(objv[3]), + " as icon window: not at top level", (char *) NULL); + return TCL_ERROR; + } + wmPtr2 = ((TkWindow *) tkwin2)->wmInfoPtr; + if (wmPtr2->iconFor != NULL) { + Tcl_AppendResult(interp, Tcl_GetString(objv[3]), + " is already an icon for ", + Tk_PathName(wmPtr2->iconFor), (char *) NULL); + return TCL_ERROR; + } + if (wmPtr->icon != NULL) { + WmInfo *wmPtr3 = ((TkWindow *) wmPtr->icon)->wmInfoPtr; + wmPtr3->iconFor = NULL; + } + Tk_MakeWindowExist(tkwin2); + wmPtr->hints.icon_window = Tk_WindowId(tkwin2); + wmPtr->hints.flags |= IconWindowHint; + wmPtr->icon = tkwin2; + wmPtr2->iconFor = (Tk_Window) winPtr; + if (!(wmPtr2->flags & WM_NEVER_MAPPED)) { + /* + * Don't have iconwindows on the Mac. We just withdraw. + */ + + Tk_UnmapWindow(tkwin2); + } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmMaxsizeCmd -- + * + * This procedure is invoked to process the "wm maxsize" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmMaxsizeCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int width, height; + + if ((objc != 3) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?"); + return TCL_ERROR; + } + if (objc == 3) { + char buf[TCL_INTEGER_SPACE * 2]; + + sprintf(buf, "%d %d", wmPtr->maxWidth, wmPtr->maxHeight); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + return TCL_OK; + } + if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK)) { + return TCL_ERROR; + } + wmPtr->maxWidth = width; + wmPtr->maxHeight = height; + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmMinsizeCmd -- + * + * This procedure is invoked to process the "wm minsize" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmMinsizeCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int width, height; + + if ((objc != 3) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?"); + return TCL_ERROR; + } + if (objc == 3) { + char buf[TCL_INTEGER_SPACE * 2]; + + sprintf(buf, "%d %d", wmPtr->minWidth, wmPtr->minHeight); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + return TCL_OK; + } + if ((Tcl_GetIntFromObj(interp, objv[3], &width) != TCL_OK) + || (Tcl_GetIntFromObj(interp, objv[4], &height) != TCL_OK)) { + return TCL_ERROR; + } + wmPtr->minWidth = width; + wmPtr->minHeight = height; + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmOverrideredirectCmd -- + * + * This procedure is invoked to process the "wm overrideredirect" + * Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmOverrideredirectCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int boolean; + XSetWindowAttributes atts; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?boolean?"); + return TCL_ERROR; + } + if (objc == 3) { + Tcl_SetBooleanObj(Tcl_GetObjResult(interp), + Tk_Attributes((Tk_Window) winPtr)->override_redirect); + return TCL_OK; + } + if (Tcl_GetBooleanFromObj(interp, objv[3], &boolean) != TCL_OK) { + return TCL_ERROR; + } + atts.override_redirect = (boolean) ? True : False; + Tk_ChangeWindowAttributes((Tk_Window) winPtr, CWOverrideRedirect, + &atts); + wmPtr->style = (boolean) ? plainDBox : documentProc; + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmPositionfromCmd -- + * + * This procedure is invoked to process the "wm positionfrom" + * Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmPositionfromCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + static CONST char *optionStrings[] = { + "program", "user", (char *) NULL }; + enum options { + OPT_PROGRAM, OPT_USER }; + int index; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?user/program?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->sizeHintsFlags & USPosition) { + Tcl_SetResult(interp, "user", TCL_STATIC); + } else if (wmPtr->sizeHintsFlags & PPosition) { + Tcl_SetResult(interp, "program", TCL_STATIC); + } + return TCL_OK; + } + if (*Tcl_GetString(objv[3]) == '\0') { + wmPtr->sizeHintsFlags &= ~(USPosition|PPosition); + } else { + if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + if (index == OPT_USER) { + wmPtr->sizeHintsFlags &= ~PPosition; + wmPtr->sizeHintsFlags |= USPosition; + } else { + wmPtr->sizeHintsFlags &= ~USPosition; + wmPtr->sizeHintsFlags |= PPosition; + } + } + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmProtocolCmd -- + * + * This procedure is invoked to process the "wm protocol" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmProtocolCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + register ProtocolHandler *protPtr, *prevPtr; + Atom protocol; + char *cmd; + int cmdLength; + + if ((objc < 3) || (objc > 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?name? ?command?"); + return TCL_ERROR; + } + if (objc == 3) { + /* + * Return a list of all defined protocols for the window. + */ + for (protPtr = wmPtr->protPtr; protPtr != NULL; + protPtr = protPtr->nextPtr) { + Tcl_AppendElement(interp, + Tk_GetAtomName((Tk_Window) winPtr, protPtr->protocol)); + } + return TCL_OK; + } + protocol = Tk_InternAtom((Tk_Window) winPtr, Tcl_GetString(objv[3])); + if (objc == 4) { + /* + * Return the command to handle a given protocol. + */ + for (protPtr = wmPtr->protPtr; protPtr != NULL; + protPtr = protPtr->nextPtr) { + if (protPtr->protocol == protocol) { + Tcl_SetResult(interp, protPtr->command, TCL_STATIC); + return TCL_OK; + } + } + return TCL_OK; + } + + /* + * Delete any current protocol handler, then create a new + * one with the specified command, unless the command is + * empty. + */ + + for (protPtr = wmPtr->protPtr, prevPtr = NULL; protPtr != NULL; + prevPtr = protPtr, protPtr = protPtr->nextPtr) { + if (protPtr->protocol == protocol) { + if (prevPtr == NULL) { + wmPtr->protPtr = protPtr->nextPtr; + } else { + prevPtr->nextPtr = protPtr->nextPtr; + } + Tcl_EventuallyFree((ClientData) protPtr, TCL_DYNAMIC); + break; + } + } + cmd = Tcl_GetStringFromObj(objv[4], &cmdLength); + if (cmdLength > 0) { + protPtr = (ProtocolHandler *) ckalloc(HANDLER_SIZE(cmdLength)); + protPtr->protocol = protocol; + protPtr->nextPtr = wmPtr->protPtr; + wmPtr->protPtr = protPtr; + protPtr->interp = interp; + strcpy(protPtr->command, cmd); + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmResizableCmd -- + * + * This procedure is invoked to process the "wm resizable" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmResizableCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + int width, height; + + if ((objc != 3) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?width height?"); + return TCL_ERROR; + } + if (objc == 3) { + char buf[TCL_INTEGER_SPACE * 2]; + + sprintf(buf, "%d %d", + (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) ? 0 : 1, + (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) ? 0 : 1); + Tcl_SetResult(interp, buf, TCL_VOLATILE); + return TCL_OK; + } + if ((Tcl_GetBooleanFromObj(interp, objv[3], &width) != TCL_OK) + || (Tcl_GetBooleanFromObj(interp, objv[4], &height) != TCL_OK)) { + return TCL_ERROR; + } + if (width) { + wmPtr->flags &= ~WM_WIDTH_NOT_RESIZABLE; + } else { + wmPtr->flags |= WM_WIDTH_NOT_RESIZABLE; + } + if (height) { + wmPtr->flags &= ~WM_HEIGHT_NOT_RESIZABLE; + } else { + wmPtr->flags |= WM_HEIGHT_NOT_RESIZABLE; + } + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + if (wmPtr->scrollWinPtr != NULL) { + TkScrollbarEventuallyRedraw( + (TkScrollbar *) wmPtr->scrollWinPtr->instanceData); + } + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmSizefromCmd -- + * + * This procedure is invoked to process the "wm sizefrom" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmSizefromCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + static CONST char *optionStrings[] = { + "program", "user", (char *) NULL }; + enum options { + OPT_PROGRAM, OPT_USER }; + int index; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?user|program?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->sizeHintsFlags & USSize) { + Tcl_SetResult(interp, "user", TCL_STATIC); + } else if (wmPtr->sizeHintsFlags & PSize) { + Tcl_SetResult(interp, "program", TCL_STATIC); + } + return TCL_OK; + } + + if (*Tcl_GetString(objv[3]) == '\0') { + wmPtr->sizeHintsFlags &= ~(USSize|PSize); + } else { + if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + if (index == OPT_USER) { + wmPtr->sizeHintsFlags &= ~PSize; + wmPtr->sizeHintsFlags |= USSize; + } else { /* OPT_PROGRAM */ + wmPtr->sizeHintsFlags &= ~USSize; + wmPtr->sizeHintsFlags |= PSize; + } + } + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + WmUpdateGeom(wmPtr, winPtr); + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmStackorderCmd -- + * + * This procedure is invoked to process the "wm stackorder" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmStackorderCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + TkWindow **windows, **window_ptr; + static CONST char *optionStrings[] = { + "isabove", "isbelow", (char *) NULL }; + enum options { + OPT_ISABOVE, OPT_ISBELOW }; + int index; + + if ((objc != 3) && (objc != 5)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?isabove|isbelow window?"); + return TCL_ERROR; + } + + if (objc == 3) { + windows = TkWmStackorderToplevel(winPtr); + if (windows == NULL) { + panic("TkWmStackorderToplevel failed"); + } else { + for (window_ptr = windows; *window_ptr ; window_ptr++) { + Tcl_AppendElement(interp, (*window_ptr)->pathName); + } + ckfree((char *) windows); + return TCL_OK; + } + } else { + TkWindow *winPtr2; + int index1=-1, index2=-1, result; + + if (TkGetWindowFromObj(interp, tkwin, objv[4], (Tk_Window *) &winPtr2) + != TCL_OK) { + return TCL_ERROR; + } + + if (!Tk_IsTopLevel(winPtr2)) { + Tcl_AppendResult(interp, "window \"", winPtr2->pathName, + "\" isn't a top-level window", (char *) NULL); + return TCL_ERROR; + } + + if (!Tk_IsMapped(winPtr)) { + Tcl_AppendResult(interp, "window \"", winPtr->pathName, + "\" isn't mapped", (char *) NULL); + return TCL_ERROR; + } + + if (!Tk_IsMapped(winPtr2)) { + Tcl_AppendResult(interp, "window \"", winPtr2->pathName, + "\" isn't mapped", (char *) NULL); + return TCL_ERROR; + } + + /* + * Lookup stacking order of all toplevels that are children + * of "." and find the position of winPtr and winPtr2 + * in the stacking order. + */ + + windows = TkWmStackorderToplevel(winPtr->mainPtr->winPtr); + + if (windows == NULL) { + Tcl_AppendResult(interp, "TkWmStackorderToplevel failed", + (char *) NULL); + return TCL_ERROR; + } else { + for (window_ptr = windows; *window_ptr ; window_ptr++) { + if (*window_ptr == winPtr) + index1 = (window_ptr - windows); + if (*window_ptr == winPtr2) + index2 = (window_ptr - windows); + } + if (index1 == -1) + panic("winPtr window not found"); + if (index2 == -1) + panic("winPtr2 window not found"); + + ckfree((char *) windows); + } + + if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + if (index == OPT_ISABOVE) { + result = index1 > index2; + } else { /* OPT_ISBELOW */ + result = index1 < index2; + } + Tcl_SetIntObj(Tcl_GetObjResult(interp), result); + return TCL_OK; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmStateCmd -- + * + * This procedure is invoked to process the "wm state" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmStateCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + static CONST char *optionStrings[] = { + "normal", "iconic", "withdrawn", "zoomed", (char *) NULL }; + enum options { + OPT_NORMAL, OPT_ICONIC, OPT_WITHDRAWN, OPT_ZOOMED }; + int index; + + if ((objc < 3) || (objc > 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?state?"); + return TCL_ERROR; + } + if (objc == 4) { + if (wmPtr->iconFor != NULL) { + Tcl_AppendResult(interp, "can't change state of ", + Tcl_GetString(objv[2]), + ": it is an icon for ", Tk_PathName(wmPtr->iconFor), + (char *) NULL); + return TCL_ERROR; + } + if (winPtr->flags & TK_EMBEDDED) { + Tcl_AppendResult(interp, "can't change state of ", + winPtr->pathName, ": it is an embedded window", + (char *) NULL); + return TCL_ERROR; + } + + if (Tcl_GetIndexFromObj(interp, objv[3], optionStrings, "argument", 0, + &index) != TCL_OK) { + return TCL_ERROR; + } + + if (index == OPT_NORMAL) { + TkpWmSetState(winPtr, NormalState); + /* + * This varies from 'wm deiconify' because it does not + * force the window to be raised and receive focus + */ + } else if (index == OPT_ICONIC) { + if (Tk_Attributes((Tk_Window) winPtr)->override_redirect) { + Tcl_AppendResult(interp, "can't iconify \"", + winPtr->pathName, + "\": override-redirect flag is set", + (char *) NULL); + return TCL_ERROR; + } + if (wmPtr->master != NULL) { + Tcl_AppendResult(interp, "can't iconify \"", + winPtr->pathName, + "\": it is a transient", (char *) NULL); + return TCL_ERROR; + } + TkpWmSetState(winPtr, IconicState); + } else if (index == OPT_WITHDRAWN) { + TkpWmSetState(winPtr, WithdrawnState); + } else { /* OPT_ZOOMED */ + TkpWmSetState(winPtr, ZoomState); + } + } else { + if (wmPtr->iconFor != NULL) { + Tcl_SetResult(interp, "icon", TCL_STATIC); + } else { + switch (wmPtr->hints.initial_state) { + case NormalState: + Tcl_SetResult(interp, "normal", TCL_STATIC); + break; + case IconicState: + Tcl_SetResult(interp, "iconic", TCL_STATIC); + break; + case WithdrawnState: + Tcl_SetResult(interp, "withdrawn", TCL_STATIC); + break; + case ZoomState: + Tcl_SetResult(interp, "zoomed", TCL_STATIC); + break; + } + } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmTitleCmd -- + * + * This procedure is invoked to process the "wm title" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmTitleCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + char *argv3; + int length; + + if (objc > 4) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?newTitle?"); + return TCL_ERROR; + } + if (objc == 3) { + Tcl_SetResult(interp, + (char *) ((wmPtr->titleUid != NULL) ? wmPtr->titleUid : winPtr->nameUid), + TCL_STATIC); + return TCL_OK; + } else { + argv3 = Tcl_GetStringFromObj(objv[3], &length); + wmPtr->titleUid = Tk_GetUid(argv3); + if (!(wmPtr->flags & WM_NEVER_MAPPED) && !Tk_IsEmbedded(winPtr)) { + TkSetWMName(winPtr, wmPtr->titleUid); + } + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmTransientCmd -- + * + * This procedure is invoked to process the "wm transient" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmTransientCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + Tk_Window master; + WmInfo *wmPtr2; + char *argv3; + int length; + + if ((objc != 3) && (objc != 4)) { + Tcl_WrongNumArgs(interp, 2, objv, "window ?master?"); + return TCL_ERROR; + } + if (objc == 3) { + if (wmPtr->master != None) { + Tcl_SetResult(interp, wmPtr->masterWindowName, TCL_STATIC); + } + return TCL_OK; + } + if (Tcl_GetString(objv[3])[0] == '\0') { + wmPtr->master = None; + if (wmPtr->masterWindowName != NULL) { + ckfree(wmPtr->masterWindowName); + } + wmPtr->masterWindowName = NULL; + wmPtr->style = documentProc; + } else { + if (TkGetWindowFromObj(interp, tkwin, objv[3], &master) != TCL_OK) { + return TCL_ERROR; + } + Tk_MakeWindowExist(master); + + if (wmPtr->iconFor != NULL) { + Tcl_AppendResult(interp, "can't make \"", + Tcl_GetString(objv[2]), + "\" a transient: it is an icon for ", + Tk_PathName(wmPtr->iconFor), + (char *) NULL); + return TCL_ERROR; + } + + wmPtr2 = ((TkWindow *) master)->wmInfoPtr; + + if (wmPtr2->iconFor != NULL) { + Tcl_AppendResult(interp, "can't make \"", + Tcl_GetString(objv[3]), + "\" a master: it is an icon for ", + Tk_PathName(wmPtr2->iconFor), + (char *) NULL); + return TCL_ERROR; + } + + argv3 = Tcl_GetStringFromObj(objv[3], &length); + wmPtr->master = Tk_WindowId(master); + wmPtr->masterWindowName = ckalloc((unsigned) length+1); + strcpy(wmPtr->masterWindowName, argv3); + wmPtr->style = plainDBox; + } + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * WmWithdrawCmd -- + * + * This procedure is invoked to process the "wm withdraw" Tcl command. + * See the user documentation for details on what it does. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * See the user documentation. + * + *---------------------------------------------------------------------- + */ + +static int +WmWithdrawCmd(tkwin, winPtr, interp, objc, objv) +Tk_Window tkwin; /* Main window of the application. */ +TkWindow *winPtr; /* Toplevel to work with */ +Tcl_Interp *interp; /* Current interpreter. */ +int objc; /* Number of arguments. */ +Tcl_Obj *CONST objv[]; /* Argument objects. */ +{ + register WmInfo *wmPtr = winPtr->wmInfoPtr; + + if (objc != 3) { + Tcl_WrongNumArgs(interp, 2, objv, "window"); + return TCL_ERROR; + } + if (wmPtr->iconFor != NULL) { + Tcl_AppendResult(interp, "can't withdraw ", Tcl_GetString(objv[2]), + ": it is an icon for ", Tk_PathName(wmPtr->iconFor), + (char *) NULL); + return TCL_ERROR; + } + TkpWmSetState(winPtr, WithdrawnState); + return TCL_OK; +} + +/* + * Invoked by those wm subcommands that affect geometry. + * Schedules a geometry update. + */ +static void +WmUpdateGeom(wmPtr, winPtr) +WmInfo *wmPtr; +TkWindow *winPtr; +{ + if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) { + Tk_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr); + wmPtr->flags |= WM_UPDATE_PENDING; + } +} +/* + *---------------------------------------------------------------------- + * + * Tk_SetGrid -- + * + * This procedure is invoked by a widget when it wishes to set a grid + * coordinate system that controls the size of a top-level window. + * It provides a C interface equivalent to the "wm grid" command and + * is usually asscoiated with the -setgrid option. + * + * Results: + * None. + * + * Side effects: + * Grid-related information will be passed to the window manager, so + * that the top-level window associated with tkwin will resize on + * even grid units. If some other window already controls gridding + * for the top-level window then this procedure call has no effect. + * + *---------------------------------------------------------------------- + */ + +void +Tk_SetGrid( + Tk_Window tkwin, /* Token for window. New window mgr info + * will be posted for the top-level window + * associated with this window. */ + int reqWidth, /* Width (in grid units) corresponding to + * the requested geometry for tkwin. */ + int reqHeight, /* Height (in grid units) corresponding to + * the requested geometry for tkwin. */ + int widthInc, int heightInc)/* Pixel increments corresponding to a + * change of one grid unit. */ +{ + TkWindow *winPtr = (TkWindow *) tkwin; + WmInfo *wmPtr; + + /* + * Find the top-level window for tkwin, plus the window manager + * information. + */ + + while (!(winPtr->flags & TK_TOP_LEVEL)) { + winPtr = winPtr->parentPtr; + } + wmPtr = winPtr->wmInfoPtr; + + if ((wmPtr->gridWin != NULL) && (wmPtr->gridWin != tkwin)) { + return; + } + + if ((wmPtr->reqGridWidth == reqWidth) + && (wmPtr->reqGridHeight == reqHeight) + && (wmPtr->widthInc == widthInc) + && (wmPtr->heightInc == heightInc) + && ((wmPtr->sizeHintsFlags & (PBaseSize|PResizeInc)) + == PBaseSize|PResizeInc)) { + return; + } + + /* + * If gridding was previously off, then forget about any window + * size requests made by the user or via "wm geometry": these are + * in pixel units and there's no easy way to translate them to + * grid units since the new requested size of the top-level window in + * pixels may not yet have been registered yet (it may filter up + * the hierarchy in DoWhenIdle handlers). However, if the window + * has never been mapped yet then just leave the window size alone: + * assume that it is intended to be in grid units but just happened + * to have been specified before this procedure was called. + */ + + if ((wmPtr->gridWin == NULL) && !(wmPtr->flags & WM_NEVER_MAPPED)) { + wmPtr->width = -1; + wmPtr->height = -1; + } + + /* + * Set the new gridding information, and start the process of passing + * all of this information to the window manager. + */ + + wmPtr->gridWin = tkwin; + wmPtr->reqGridWidth = reqWidth; + wmPtr->reqGridHeight = reqHeight; + wmPtr->widthInc = widthInc; + wmPtr->heightInc = heightInc; + wmPtr->sizeHintsFlags |= PBaseSize|PResizeInc; + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) { + Tk_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr); + wmPtr->flags |= WM_UPDATE_PENDING; + } +} + +/* + *---------------------------------------------------------------------- + * + * Tk_UnsetGrid -- + * + * This procedure cancels the effect of a previous call + * to Tk_SetGrid. + * + * Results: + * None. + * + * Side effects: + * If tkwin currently controls gridding for its top-level window, + * gridding is cancelled for that top-level window; if some other + * window controls gridding then this procedure has no effect. + * + *---------------------------------------------------------------------- + */ + +void +Tk_UnsetGrid( + Tk_Window tkwin) /* Token for window that is currently + * controlling gridding. */ +{ + TkWindow *winPtr = (TkWindow *) tkwin; + WmInfo *wmPtr; + + /* + * Find the top-level window for tkwin, plus the window manager + * information. + */ + + while (!(winPtr->flags & TK_TOP_LEVEL)) { + winPtr = winPtr->parentPtr; + } + wmPtr = winPtr->wmInfoPtr; + if (tkwin != wmPtr->gridWin) { + return; + } + + wmPtr->gridWin = NULL; + wmPtr->sizeHintsFlags &= ~(PBaseSize|PResizeInc); + if (wmPtr->width != -1) { + wmPtr->width = winPtr->reqWidth + (wmPtr->width + - wmPtr->reqGridWidth)*wmPtr->widthInc; + wmPtr->height = winPtr->reqHeight + (wmPtr->height + - wmPtr->reqGridHeight)*wmPtr->heightInc; + } + wmPtr->widthInc = 1; + wmPtr->heightInc = 1; + + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) { + Tk_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr); + wmPtr->flags |= WM_UPDATE_PENDING; + } +} + +/* + *---------------------------------------------------------------------- + * + * TopLevelEventProc -- + * + * This procedure is invoked when a top-level (or other externally- + * managed window) is restructured in any way. + * + * Results: + * None. + * + * Side effects: + * Tk's internal data structures for the window get modified to + * reflect the structural change. + * + *---------------------------------------------------------------------- + */ + +static void +TopLevelEventProc( + ClientData clientData, /* Window for which event occurred. */ + XEvent *eventPtr) /* Event that just happened. */ +{ + TkWindow *winPtr = (TkWindow *) clientData; + + winPtr->wmInfoPtr->flags |= WM_VROOT_OFFSET_STALE; + if (eventPtr->type == DestroyNotify) { + Tk_ErrorHandler handler; + + if (!(winPtr->flags & TK_ALREADY_DEAD)) { + /* + * A top-level window was deleted externally (e.g., by the window + * manager). This is probably not a good thing, but cleanup as + * best we can. The error handler is needed because + * Tk_DestroyWindow will try to destroy the window, but of course + * it's already gone. + */ + + handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1, + (Tk_ErrorProc *) NULL, (ClientData) NULL); + Tk_DestroyWindow((Tk_Window) winPtr); + Tk_DeleteErrorHandler(handler); + } + if (wmTracing) { + printf("TopLevelEventProc: %s deleted\n", winPtr->pathName); + } + } else if (eventPtr->type == ReparentNotify) { + panic("recieved unwanted reparent event"); + } +} + +/* + *---------------------------------------------------------------------- + * + * TopLevelReqProc -- + * + * This procedure is invoked by the geometry manager whenever + * the requested size for a top-level window is changed. + * + * Results: + * None. + * + * Side effects: + * Arrange for the window to be resized to satisfy the request + * (this happens as a when-idle action). + * + *---------------------------------------------------------------------- + */ + + /* ARGSUSED */ +static void +TopLevelReqProc( + ClientData dummy, /* Not used. */ + Tk_Window tkwin) /* Information about window. */ +{ + TkWindow *winPtr = (TkWindow *) tkwin; + WmInfo *wmPtr; + + wmPtr = winPtr->wmInfoPtr; + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) { + Tk_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr); + wmPtr->flags |= WM_UPDATE_PENDING; + } +} + +/* + *---------------------------------------------------------------------- + * + * UpdateGeometryInfo -- + * + * This procedure is invoked when a top-level window is first + * mapped, and also as a when-idle procedure, to bring the + * geometry and/or position of a top-level window back into + * line with what has been requested by the user and/or widgets. + * This procedure doesn't return until the window manager has + * responded to the geometry change. + * + * Results: + * None. + * + * Side effects: + * The window's size and location may change, unless the WM prevents + * that from happening. + * + *---------------------------------------------------------------------- + */ + +static void +UpdateGeometryInfo( + ClientData clientData) /* Pointer to the window's record. */ +{ + TkWindow *winPtr = (TkWindow *) clientData; + WmInfo *wmPtr = winPtr->wmInfoPtr; + int x, y, width, height; + unsigned long serial; + + wmPtr->flags &= ~WM_UPDATE_PENDING; + + /* + * Compute the new size for the top-level window. See the + * user documentation for details on this, but the size + * requested depends on (a) the size requested internally + * by the window's widgets, (b) the size requested by the + * user in a "wm geometry" command or via wm-based interactive + * resizing (if any), and (c) whether or not the window is + * gridded. Don't permit sizes <= 0 because this upsets + * the X server. + */ + + if (wmPtr->width == -1) { + width = winPtr->reqWidth; + } else if (wmPtr->gridWin != NULL) { + width = winPtr->reqWidth + + (wmPtr->width - wmPtr->reqGridWidth)*wmPtr->widthInc; + } else { + width = wmPtr->width; + } + if (width <= 0) { + width = 1; + } + if (wmPtr->height == -1) { + height = winPtr->reqHeight; + } else if (wmPtr->gridWin != NULL) { + height = winPtr->reqHeight + + (wmPtr->height - wmPtr->reqGridHeight)*wmPtr->heightInc; + } else { + height = wmPtr->height; + } + if (height <= 0) { + height = 1; + } + + /* + * Compute the new position for the upper-left pixel of the window's + * decorative frame. This is tricky, because we need to include the + * border widths supplied by a reparented parent in this calculation, + * but can't use the parent's current overall size since that may + * change as a result of this code. + */ + + if (wmPtr->flags & WM_NEGATIVE_X) { + x = wmPtr->vRootWidth - wmPtr->x + - (width + (wmPtr->parentWidth - winPtr->changes.width)); + } else { + x = wmPtr->x; + } + if (wmPtr->flags & WM_NEGATIVE_Y) { + y = wmPtr->vRootHeight - wmPtr->y + - (height + (wmPtr->parentHeight - winPtr->changes.height)); + } else { + y = wmPtr->y; + } + + /* + * If the window's size is going to change and the window is + * supposed to not be resizable by the user, then we have to + * update the size hints. There may also be a size-hint-update + * request pending from somewhere else, too. + */ + + if (((width != winPtr->changes.width) + || (height != winPtr->changes.height)) + && (wmPtr->gridWin == NULL) + && ((wmPtr->sizeHintsFlags & (PMinSize|PMaxSize)) == 0)) { + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + } + if (wmPtr->flags & WM_UPDATE_SIZE_HINTS) { + UpdateSizeHints(winPtr); + } + + /* + * Reconfigure the window if it isn't already configured correctly. + * A few tricky points: + * + * 1. If the window is embedded and the container is also in this + * process, don't actually reconfigure the window; just pass the + * desired size on to the container. Also, zero out any position + * information, since embedded windows are not allowed to move. + * 2. Sometimes the window manager will give us a different size + * than we asked for (e.g. mwm has a minimum size for windows), so + * base the size check on what we *asked for* last time, not what we + * got. + * 3. Don't move window unless a new position has been requested for + * it. This is because of "features" in some window managers (e.g. + * twm, as of 4/24/91) where they don't interpret coordinates + * according to ICCCM. Moving a window to its current location may + * cause it to shift position on the screen. + */ + + if (Tk_IsEmbedded(winPtr)) { + TkWindow *contWinPtr; + + contWinPtr = TkpGetOtherWindow(winPtr); + + /* + * NOTE: Here we should handle out of process embedding. + */ + + if (contWinPtr != NULL) { + /* + * This window is embedded and the container is also in this + * process, so we don't need to do anything special about the + * geometry, except to make sure that the desired size is known + * by the container. Also, zero out any position information, + * since embedded windows are not allowed to move. + */ + + wmPtr->x = wmPtr->y = 0; + wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y); + Tk_GeometryRequest((Tk_Window) contWinPtr, width, height); + } + return; + } + serial = NextRequest(winPtr->display); + if (wmPtr->flags & WM_MOVE_PENDING) { + wmPtr->configWidth = width; + wmPtr->configHeight = height; + if (wmTracing) { + printf( + "UpdateGeometryInfo moving to %d %d, resizing to %d x %d,\n", + x, y, width, height); + } + Tk_MoveResizeWindow((Tk_Window) winPtr, x, y, (unsigned) width, + (unsigned) height); + } else if ((width != wmPtr->configWidth) + || (height != wmPtr->configHeight)) { + wmPtr->configWidth = width; + wmPtr->configHeight = height; + if (wmTracing) { + printf("UpdateGeometryInfo resizing to %d x %d\n", width, height); + } + Tk_ResizeWindow((Tk_Window) winPtr, (unsigned) width, + (unsigned) height); + } else { + return; + } +} + +/* + *-------------------------------------------------------------- + * + * UpdateSizeHints -- + * + * This procedure is called to update the window manager's + * size hints information from the information in a WmInfo + * structure. + * + * Results: + * None. + * + * Side effects: + * Properties get changed for winPtr. + * + *-------------------------------------------------------------- + */ + +static void +UpdateSizeHints( + TkWindow *winPtr) +{ + WmInfo *wmPtr = winPtr->wmInfoPtr; + XSizeHints *hintsPtr; + + wmPtr->flags &= ~WM_UPDATE_SIZE_HINTS; + + hintsPtr = XAllocSizeHints(); + if (hintsPtr == NULL) { + return; + } + + /* + * Compute the pixel-based sizes for the various fields in the + * size hints structure, based on the grid-based sizes in + * our structure. + */ + + if (wmPtr->gridWin != NULL) { + hintsPtr->base_width = winPtr->reqWidth + - (wmPtr->reqGridWidth * wmPtr->widthInc); + if (hintsPtr->base_width < 0) { + hintsPtr->base_width = 0; + } + hintsPtr->base_height = winPtr->reqHeight + - (wmPtr->reqGridHeight * wmPtr->heightInc); + if (hintsPtr->base_height < 0) { + hintsPtr->base_height = 0; + } + hintsPtr->min_width = hintsPtr->base_width + + (wmPtr->minWidth * wmPtr->widthInc); + hintsPtr->min_height = hintsPtr->base_height + + (wmPtr->minHeight * wmPtr->heightInc); + hintsPtr->max_width = hintsPtr->base_width + + (wmPtr->maxWidth * wmPtr->widthInc); + hintsPtr->max_height = hintsPtr->base_height + + (wmPtr->maxHeight * wmPtr->heightInc); + } else { + hintsPtr->min_width = wmPtr->minWidth; + hintsPtr->min_height = wmPtr->minHeight; + hintsPtr->max_width = wmPtr->maxWidth; + hintsPtr->max_height = wmPtr->maxHeight; + hintsPtr->base_width = 0; + hintsPtr->base_height = 0; + } + hintsPtr->width_inc = wmPtr->widthInc; + hintsPtr->height_inc = wmPtr->heightInc; + hintsPtr->min_aspect.x = wmPtr->minAspect.x; + hintsPtr->min_aspect.y = wmPtr->minAspect.y; + hintsPtr->max_aspect.x = wmPtr->maxAspect.x; + hintsPtr->max_aspect.y = wmPtr->maxAspect.y; + hintsPtr->win_gravity = wmPtr->gravity; + hintsPtr->flags = wmPtr->sizeHintsFlags | PMinSize | PMaxSize; + + /* + * If the window isn't supposed to be resizable, then set the + * minimum and maximum dimensions to be the same. + */ + + if (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) { + if (wmPtr->width >= 0) { + hintsPtr->min_width = wmPtr->width; + } else { + hintsPtr->min_width = winPtr->reqWidth; + } + hintsPtr->max_width = hintsPtr->min_width; + } + if (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) { + if (wmPtr->height >= 0) { + hintsPtr->min_height = wmPtr->height; + } else { + hintsPtr->min_height = winPtr->reqHeight; + } + hintsPtr->max_height = hintsPtr->min_height; + } + + XSetWMNormalHints(winPtr->display, winPtr->window, hintsPtr); + + XFree((char *) hintsPtr); +} + +/* + *-------------------------------------------------------------- + * + * ParseGeometry -- + * + * This procedure parses a geometry string and updates + * information used to control the geometry of a top-level + * window. + * + * Results: + * A standard Tcl return value, plus an error message in + * the interp's result if an error occurs. + * + * Side effects: + * The size and/or location of winPtr may change. + * + *-------------------------------------------------------------- + */ + +static int +ParseGeometry( + Tcl_Interp *interp, /* Used for error reporting. */ + char *string, /* String containing new geometry. Has the + * standard form "=wxh+x+y". */ + TkWindow *winPtr) /* Pointer to top-level window whose + * geometry is to be changed. */ +{ + WmInfo *wmPtr = winPtr->wmInfoPtr; + int x, y, width, height, flags; + char *end; + char *p = string; + + /* + * The leading "=" is optional. + */ + + if (*p == '=') { + p++; + } + + /* + * Parse the width and height, if they are present. Don't + * actually update any of the fields of wmPtr until we've + * successfully parsed the entire geometry string. + */ + + width = wmPtr->width; + height = wmPtr->height; + x = wmPtr->x; + y = wmPtr->y; + flags = wmPtr->flags; + if (isdigit(UCHAR(*p))) { + width = strtoul(p, &end, 10); + p = end; + if (*p != 'x') { + goto error; + } + p++; + if (!isdigit(UCHAR(*p))) { + goto error; + } + height = strtoul(p, &end, 10); + p = end; + } + + /* + * Parse the X and Y coordinates, if they are present. + */ + + if (*p != '\0') { + flags &= ~(WM_NEGATIVE_X | WM_NEGATIVE_Y); + if (*p == '-') { + flags |= WM_NEGATIVE_X; + } else if (*p != '+') { + goto error; + } + x = strtol(p+1, &end, 10); + p = end; + if (*p == '-') { + flags |= WM_NEGATIVE_Y; + } else if (*p != '+') { + goto error; + } + y = strtol(p+1, &end, 10); + if (*end != '\0') { + goto error; + } + + /* + * Assume that the geometry information came from the user, + * unless an explicit source has been specified. Otherwise + * most window managers assume that the size hints were + * program-specified and they ignore them. + */ + + if ((wmPtr->sizeHintsFlags & (USPosition|PPosition)) == 0) { + wmPtr->sizeHintsFlags |= USPosition; + flags |= WM_UPDATE_SIZE_HINTS; + } + } + + /* + * Everything was parsed OK. Update the fields of *wmPtr and + * arrange for the appropriate information to be percolated out + * to the window manager at the next idle moment. + */ + + wmPtr->width = width; + wmPtr->height = height; + if ((x != wmPtr->x) || (y != wmPtr->y) + || ((flags & (WM_NEGATIVE_X|WM_NEGATIVE_Y)) + != (wmPtr->flags & (WM_NEGATIVE_X|WM_NEGATIVE_Y)))) { + wmPtr->x = x; + wmPtr->y = y; + flags |= WM_MOVE_PENDING; + } + wmPtr->flags = flags; + + if (!(wmPtr->flags & (WM_UPDATE_PENDING|WM_NEVER_MAPPED))) { + Tk_DoWhenIdle(UpdateGeometryInfo, (ClientData) winPtr); + wmPtr->flags |= WM_UPDATE_PENDING; + } + return TCL_OK; + + error: + Tcl_AppendResult(interp, "bad geometry specifier \"", + string, "\"", (char *) NULL); + return TCL_ERROR; +} + +/* + *---------------------------------------------------------------------- + * + * Tk_GetRootCoords -- + * + * Given a token for a window, this procedure traces through the + * window's lineage to find the (virtual) root-window coordinates + * corresponding to point (0,0) in the window. + * + * Results: + * The locations pointed to by xPtr and yPtr are filled in with + * the root coordinates of the (0,0) point in tkwin. If a virtual + * root window is in effect for the window, then the coordinates + * in the virtual root are returned. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +Tk_GetRootCoords( + Tk_Window tkwin, /* Token for window. */ + int *xPtr, /* Where to store x-displacement of (0,0). */ + int *yPtr) /* Where to store y-displacement of (0,0). */ +{ + int x, y; + TkWindow *winPtr = (TkWindow *) tkwin; + + /* + * Search back through this window's parents all the way to a + * top-level window, combining the offsets of each window within + * its parent. + */ + + x = y = 0; + while (1) { + x += winPtr->changes.x + winPtr->changes.border_width; + y += winPtr->changes.y + winPtr->changes.border_width; + if (winPtr->flags & TK_TOP_LEVEL) { + if (!(Tk_IsEmbedded(winPtr))) { + x += winPtr->wmInfoPtr->xInParent; + y += winPtr->wmInfoPtr->yInParent; + break; + } else { + TkWindow *otherPtr; + + otherPtr = TkpGetOtherWindow(winPtr); + if (otherPtr != NULL) { + /* + * The container window is in the same application. + * Query its coordinates. + */ + winPtr = otherPtr; + + /* + * Remember to offset by the container window here, + * since at the end of this if branch, we will + * pop out to the container's parent... + */ + + x += winPtr->changes.x + winPtr->changes.border_width; + y += winPtr->changes.y + winPtr->changes.border_width; + + } else { + Point theOffset; + + if (gMacEmbedHandler->getOffsetProc != NULL) { + /* + * We do not require that the changes.x & changes.y for + * a non-Tk master window be kept up to date. So we + * first subtract off the possibly bogus values that have + * been added on at the top of this pass through the loop, + * and then call out to the getOffsetProc to give us + * the correct offset. + */ + + x -= winPtr->changes.x + winPtr->changes.border_width; + y -= winPtr->changes.y + winPtr->changes.border_width; + + gMacEmbedHandler->getOffsetProc((Tk_Window) winPtr, &theOffset); + + x += theOffset.h; + y += theOffset.v; + } + break; + } + } + } + winPtr = winPtr->parentPtr; + } + *xPtr = x; + *yPtr = y; +} + +/* + *---------------------------------------------------------------------- + * + * Tk_CoordsToWindow -- + * + * This is a Macintosh specific implementation of this function. + * Given the root coordinates of a point, this procedure returns + * the token for the top-most window covering that point, if + * there exists such a window in this application. + * + * Results: + * The return result is either a token for the window corresponding + * to rootX and rootY, or else NULL to indicate that there is no such + * window. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Tk_Window +Tk_CoordsToWindow( + int rootX, int rootY, /* Coordinates of point in root window. If + * a virtual-root window manager is in use, + * these coordinates refer to the virtual + * root, not the real root. */ + Tk_Window tkwin) /* Token for any window in application; + * used to identify the display. */ +{ + WindowPtr whichWin; + Point where; + Window rootChild; + TkWindow *winPtr, *childPtr; + TkWindow *nextPtr; /* Coordinates of highest child found so + * far that contains point. */ + int x, y; /* Coordinates in winPtr. */ + int tmpx, tmpy, bd; + TkDisplay *dispPtr; + + /* + * Step 1: find the top-level window that contains the desired point. + */ + + where.h = rootX; + where.v = rootY; + FindWindow(where, &whichWin); + if (whichWin == NULL) { + return NULL; + } + rootChild = TkMacOSXGetXWindow(whichWin); + dispPtr = TkGetDisplayList(); + winPtr = (TkWindow *) Tk_IdToWindow(dispPtr->display, rootChild); + if (winPtr == NULL) { + return NULL; + } + + /* + * Step 2: work down through the hierarchy underneath this window. + * At each level, scan through all the children to find the highest + * one in the stacking order that contains the point. Then repeat + * the whole process on that child. + */ + + x = rootX - winPtr->wmInfoPtr->xInParent; + y = rootY - winPtr->wmInfoPtr->yInParent; + while (1) { + x -= winPtr->changes.x; + y -= winPtr->changes.y; + nextPtr = NULL; + + /* + * Container windows cannot have children. So if it is a container, + * look there, otherwise inspect the children. + */ + + if (Tk_IsContainer(winPtr)) { + childPtr = TkpGetOtherWindow(winPtr); + if (childPtr != NULL) { + if (Tk_IsMapped(childPtr)) { + tmpx = x - childPtr->changes.x; + tmpy = y - childPtr->changes.y; + bd = childPtr->changes.border_width; + + if ((tmpx >= -bd) && (tmpy >= -bd) + && (tmpx < (childPtr->changes.width + bd)) + && (tmpy < (childPtr->changes.height + bd))) { + nextPtr = childPtr; + } + } + } + + + /* + * NOTE: Here we should handle out of process embedding. + */ + + } else { + for (childPtr = winPtr->childList; childPtr != NULL; + childPtr = childPtr->nextPtr) { + if (!Tk_IsMapped(childPtr) || + (childPtr->flags & TK_TOP_LEVEL)) { + continue; + } + tmpx = x - childPtr->changes.x; + tmpy = y - childPtr->changes.y; + bd = childPtr->changes.border_width; + if ((tmpx >= -bd) && (tmpy >= -bd) + && (tmpx < (childPtr->changes.width + bd)) + && (tmpy < (childPtr->changes.height + bd))) { + nextPtr = childPtr; + } + } + } + if (nextPtr == NULL) { + break; + } + winPtr = nextPtr; + } + return (Tk_Window) winPtr; +} + +/* + *---------------------------------------------------------------------- + * + * Tk_TopCoordsToWindow -- + * + * Given a Tk Window, and coordinates of a point relative to that window + * this procedure returns the top-most child of the window (excluding + * toplevels) covering that point, if there exists such a window in this + * application. + * It also sets newX, and newY to the coords of the point relative to the + * window returned. + * + * Results: + * The return result is either a token for the window corresponding + * to rootX and rootY, or else NULL to indicate that there is no such + * window. newX and newY are also set to the coords of the point relative + * to the returned window. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Tk_Window +Tk_TopCoordsToWindow( + Tk_Window tkwin, /* Token for a Tk Window which defines the; + * coordinates for rootX & rootY */ + int rootX, int rootY, /* Coordinates of a point in tkWin. */ + int *newX, int *newY) /* Coordinates of point in the upperMost child of + * tkWin containing (rootX,rootY) */ +{ + TkWindow *winPtr, *childPtr; + TkWindow *nextPtr; /* Coordinates of highest child found so + * far that contains point. */ + int x, y; /* Coordinates in winPtr. */ + Window *children; /* Children of winPtr, or NULL. */ + + winPtr = (TkWindow *) tkwin; + x = rootX; + y = rootY; + while (1) { + nextPtr = NULL; + children = NULL; + + /* + * Container windows cannot have children. So if it is a container, + * look there, otherwise inspect the children. + */ + + if (Tk_IsContainer(winPtr)) { + childPtr = TkpGetOtherWindow(winPtr); + if (childPtr != NULL) { + if (Tk_IsMapped(childPtr) && + (x > childPtr->changes.x && + x < childPtr->changes.x + + childPtr->changes.width) && + (y > childPtr->changes.y && + y < childPtr->changes.y + + childPtr->changes.height)) { + nextPtr = childPtr; + } + } + + /* + * NOTE: Here we should handle out of process embedding. + */ + + } else { + + for (childPtr = winPtr->childList; childPtr != NULL; + childPtr = childPtr->nextPtr) { + if (!Tk_IsMapped(childPtr) || + (childPtr->flags & TK_TOP_LEVEL)) { + continue; + } + if (x < childPtr->changes.x || y < childPtr->changes.y) { + continue; + } + if (x > childPtr->changes.x + childPtr->changes.width || + y > childPtr->changes.y + childPtr->changes.height) { + continue; + } + nextPtr = childPtr; + } + } + if (nextPtr == NULL) { + break; + } + winPtr = nextPtr; + x -= winPtr->changes.x; + y -= winPtr->changes.y; + } + *newX = x; + *newY = y; + return (Tk_Window) winPtr; +} + +/* + *---------------------------------------------------------------------- + * + * UpdateVRootGeometry -- + * + * This procedure is called to update all the virtual root + * geometry information in wmPtr. + * + * Results: + * None. + * + * Side effects: + * The vRootX, vRootY, vRootWidth, and vRootHeight fields in + * wmPtr are filled with the most up-to-date information. + * + *---------------------------------------------------------------------- + */ + +static void +UpdateVRootGeometry( + WmInfo *wmPtr) /* Window manager information to be + * updated. The wmPtr->vRoot field must + * be valid. */ +{ + TkWindow *winPtr = wmPtr->winPtr; + unsigned int bd, dummy; + Window dummy2; + Status status; + Tk_ErrorHandler handler; + + /* + * If this isn't a virtual-root window manager, just return information + * about the screen. + */ + + wmPtr->flags &= ~WM_VROOT_OFFSET_STALE; + if (wmPtr->vRoot == None) { + noVRoot: + wmPtr->vRootX = wmPtr->vRootY = 0; + wmPtr->vRootWidth = DisplayWidth(winPtr->display, winPtr->screenNum); + wmPtr->vRootHeight = DisplayHeight(winPtr->display, winPtr->screenNum); + return; + } + + /* + * Refresh the virtual root information if it's out of date. + */ + + handler = Tk_CreateErrorHandler(winPtr->display, -1, -1, -1, + (Tk_ErrorProc *) NULL, (ClientData) NULL); + status = XGetGeometry(winPtr->display, wmPtr->vRoot, + &dummy2, &wmPtr->vRootX, &wmPtr->vRootY, + &wmPtr->vRootWidth, &wmPtr->vRootHeight, &bd, &dummy); + if (wmTracing) { + printf("UpdateVRootGeometry: x = %d, y = %d, width = %d, ", + wmPtr->vRootX, wmPtr->vRootY, wmPtr->vRootWidth); + printf("height = %d, status = %d\n", wmPtr->vRootHeight, status); + } + Tk_DeleteErrorHandler(handler); + if (status == 0) { + /* + * The virtual root is gone! Pretend that it never existed. + */ + + wmPtr->vRoot = None; + goto noVRoot; + } +} + +/* + *---------------------------------------------------------------------- + * + * Tk_GetVRootGeometry -- + * + * This procedure returns information about the virtual root + * window corresponding to a particular Tk window. + * + * Results: + * The values at xPtr, yPtr, widthPtr, and heightPtr are set + * with the offset and dimensions of the root window corresponding + * to tkwin. If tkwin is being managed by a virtual root window + * manager these values correspond to the virtual root window being + * used for tkwin; otherwise the offsets will be 0 and the + * dimensions will be those of the screen. + * + * Side effects: + * Vroot window information is refreshed if it is out of date. + * + *---------------------------------------------------------------------- + */ + +void +Tk_GetVRootGeometry( + Tk_Window tkwin, /* Window whose virtual root is to be + * queried. */ + int *xPtr, int *yPtr, /* Store x and y offsets of virtual root + * here. */ + int *widthPtr, /* Store dimensions of virtual root here. */ + int *heightPtr) +{ + WmInfo *wmPtr; + TkWindow *winPtr = (TkWindow *) tkwin; + + /* + * Find the top-level window for tkwin, and locate the window manager + * information for that window. + */ + + while (!(winPtr->flags & TK_TOP_LEVEL)) { + winPtr = winPtr->parentPtr; + } + wmPtr = winPtr->wmInfoPtr; + + /* + * Make sure that the geometry information is up-to-date, then copy + * it out to the caller. + */ + + if (wmPtr->flags & WM_VROOT_OFFSET_STALE) { + UpdateVRootGeometry(wmPtr); + } + *xPtr = wmPtr->vRootX; + *yPtr = wmPtr->vRootY; + *widthPtr = wmPtr->vRootWidth; + *heightPtr = wmPtr->vRootHeight; +} + +/* + *---------------------------------------------------------------------- + * + * Tk_MoveToplevelWindow -- + * + * This procedure is called instead of Tk_MoveWindow to adjust + * the x-y location of a top-level window. It delays the actual + * move to a later time and keeps window-manager information + * up-to-date with the move + * + * Results: + * None. + * + * Side effects: + * The window is eventually moved so that its upper-left corner + * (actually, the upper-left corner of the window's decorative + * frame, if there is one) is at (x,y). + * + *---------------------------------------------------------------------- + */ + +void +Tk_MoveToplevelWindow( + Tk_Window tkwin, /* Window to move. */ + int x, int y) /* New location for window (within + * parent). */ +{ + TkWindow *winPtr = (TkWindow *) tkwin; + WmInfo *wmPtr = winPtr->wmInfoPtr; + + if (!(winPtr->flags & TK_TOP_LEVEL)) { + panic("Tk_MoveToplevelWindow called with non-toplevel window"); + } + wmPtr->x = x; + wmPtr->y = y; + wmPtr->flags |= WM_MOVE_PENDING; + wmPtr->flags &= ~(WM_NEGATIVE_X|WM_NEGATIVE_Y); + if ((wmPtr->sizeHintsFlags & (USPosition|PPosition)) == 0) { + wmPtr->sizeHintsFlags |= USPosition; + wmPtr->flags |= WM_UPDATE_SIZE_HINTS; + } + + /* + * If the window has already been mapped, must bring its geometry + * up-to-date immediately, otherwise an event might arrive from the + * server that would overwrite wmPtr->x and wmPtr->y and lose the + * new position. + */ + + if (!(wmPtr->flags & WM_NEVER_MAPPED)) { + if (wmPtr->flags & WM_UPDATE_PENDING) { + Tk_CancelIdleCall(UpdateGeometryInfo, (ClientData) winPtr); + } + UpdateGeometryInfo((ClientData) winPtr); + } +} +/* + *---------------------------------------------------------------------- + * + * TkWmRestackToplevel -- + * + * This procedure restacks a top-level window. + * + * Results: + * None. + * + * Side effects: + * WinPtr gets restacked as specified by aboveBelow and otherPtr. + * This procedure doesn't return until the restack has taken + * effect and the ConfigureNotify event for it has been received. + * + *---------------------------------------------------------------------- + */ + +void +TkWmRestackToplevel( + TkWindow *winPtr, /* Window to restack. */ + int aboveBelow, /* Gives relative position for restacking; + * must be Above or Below. */ + TkWindow *otherPtr) /* Window relative to which to restack; + * if NULL, then winPtr gets restacked + * above or below *all* siblings. */ +{ + WmInfo *wmPtr; + + WindowRef macWindow, otherMacWindow, frontWindow, tmpWindow; + + wmPtr = winPtr->wmInfoPtr; + + /* + * Get the mac window. Make sure it exists & is mapped. + */ + + if (winPtr->window == None) { + Tk_MakeWindowExist((Tk_Window) winPtr); + } + if (winPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) { + + /* + * Can't set stacking order properly until the window is on the + * screen (mapping it may give it a reparent window), so make sure + * it's on the screen. + */ + + TkWmMapWindow(winPtr); + } + macWindow = GetWindowFromPort(TkMacOSXGetDrawablePort(winPtr->window)); + + /* + * Get the window in which a raise or lower is in relation to. + */ + if (otherPtr != NULL) { + if (otherPtr->window == None) { + Tk_MakeWindowExist((Tk_Window) otherPtr); + } + if (otherPtr->wmInfoPtr->flags & WM_NEVER_MAPPED) { + TkWmMapWindow(otherPtr); + } + otherMacWindow =GetWindowFromPort(TkMacOSXGetDrawablePort(otherPtr->window)); + } else { + otherMacWindow = NULL; + } + + + frontWindow = FrontNonFloatingWindow(); + + if (aboveBelow == Above) { + if (macWindow == frontWindow) { + /* + * Do nothing - it's already at the top. + */ + } else if (otherMacWindow == frontWindow || otherMacWindow == NULL) { + /* + * Raise the window to the top. If the window is visable then + * we also make it the active window. + */ + + if (wmPtr->hints.initial_state == WithdrawnState) { + BringToFront(macWindow); + } else { + SelectWindow(macWindow); + } + } else { + /* + * Find the window to be above. (Front window will actually be the + * window to be behind.) Front window is NULL if no other windows. + */ + while (frontWindow != NULL && + ( tmpWindow = GetNextWindow (frontWindow) ) != otherMacWindow) { + frontWindow = tmpWindow; + } + if (frontWindow != NULL) { + SendBehind(macWindow, frontWindow); + } + } + } else { + /* + * Send behind. If it was in front find another window to make active. + */ + if (macWindow == frontWindow) { + if ( ( tmpWindow = GetNextWindow ( macWindow )) != NULL) { + SelectWindow(tmpWindow); + } + } + SendBehind(macWindow, otherMacWindow); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkWmAddToColormapWindows -- + * + * This procedure is called to add a given window to the + * WM_COLORMAP_WINDOWS property for its top-level, if it + * isn't already there. It is invoked by the Tk code that + * creates a new colormap, in order to make sure that colormap + * information is propagated to the window manager by default. + * + * Results: + * None. + * + * Side effects: + * WinPtr's window gets added to the WM_COLORMAP_WINDOWS + * property of its nearest top-level ancestor, unless the + * colormaps have been set explicitly with the + * "wm colormapwindows" command. + * + *---------------------------------------------------------------------- + */ + +void +TkWmAddToColormapWindows( + TkWindow *winPtr) /* Window with a non-default colormap. + * Should not be a top-level window. */ +{ + TkWindow *topPtr; + TkWindow **oldPtr, **newPtr; + int count, i; + + if (winPtr->window == None) { + return; + } + + for (topPtr = winPtr->parentPtr; ; topPtr = topPtr->parentPtr) { + if (topPtr == NULL) { + /* + * Window is being deleted. Skip the whole operation. + */ + + return; + } + if (topPtr->flags & TK_TOP_LEVEL) { + break; + } + } + if (topPtr->wmInfoPtr->flags & WM_COLORMAPS_EXPLICIT) { + return; + } + + /* + * Make sure that the window isn't already in the list. + */ + + count = topPtr->wmInfoPtr->cmapCount; + oldPtr = topPtr->wmInfoPtr->cmapList; + + for (i = 0; i < count; i++) { + if (oldPtr[i] == winPtr) { + return; + } + } + + /* + * Make a new bigger array and use it to reset the property. + * Automatically add the toplevel itself as the last element + * of the list. + */ + + newPtr = (TkWindow **) ckalloc((unsigned) ((count+2)*sizeof(TkWindow*))); + if (count > 0) { + memcpy(newPtr, oldPtr, count * sizeof(TkWindow*)); + } + if (count == 0) { + count++; + } + newPtr[count-1] = winPtr; + newPtr[count] = topPtr; + if (oldPtr != NULL) { + ckfree((char *) oldPtr); + } + + topPtr->wmInfoPtr->cmapList = newPtr; + topPtr->wmInfoPtr->cmapCount = count+1; + + /* + * On the Macintosh all of this is just an excercise + * in compatability as we don't support colormaps. If + * we did they would be installed here. + */ +} + +/* + *---------------------------------------------------------------------- + * + * TkWmRemoveFromColormapWindows -- + * + * This procedure is called to remove a given window from the + * WM_COLORMAP_WINDOWS property for its top-level. It is invoked + * when windows are deleted. + * + * Results: + * None. + * + * Side effects: + * WinPtr's window gets removed from the WM_COLORMAP_WINDOWS + * property of its nearest top-level ancestor, unless the + * top-level itself is being deleted too. + * + *---------------------------------------------------------------------- + */ + +void +TkWmRemoveFromColormapWindows( + TkWindow *winPtr) /* Window that may be present in + * WM_COLORMAP_WINDOWS property for its + * top-level. Should not be a top-level + * window. */ +{ + TkWindow *topPtr; + TkWindow **oldPtr; + int count, i, j; + + for (topPtr = winPtr->parentPtr; ; topPtr = topPtr->parentPtr) { + if (topPtr == NULL) { + /* + * Ancestors have been deleted, so skip the whole operation. + * Seems like this can't ever happen? + */ + + return; + } + if (topPtr->flags & TK_TOP_LEVEL) { + break; + } + } + if (topPtr->flags & TK_ALREADY_DEAD) { + /* + * Top-level is being deleted, so there's no need to cleanup + * the WM_COLORMAP_WINDOWS property. + */ + + return; + } + + /* + * Find the window and slide the following ones down to cover + * it up. + */ + + count = topPtr->wmInfoPtr->cmapCount; + oldPtr = topPtr->wmInfoPtr->cmapList; + for (i = 0; i < count; i++) { + if (oldPtr[i] == winPtr) { + for (j = i ; j < count-1; j++) { + oldPtr[j] = oldPtr[j+1]; + } + topPtr->wmInfoPtr->cmapCount = count - 1; + break; + } + } +} + +/* + *---------------------------------------------------------------------- + * + * TkGetPointerCoords -- + * + * Fetch the position of the mouse pointer. + * + * Results: + * *xPtr and *yPtr are filled in with the (virtual) root coordinates + * of the mouse pointer for tkwin's display. If the pointer isn't + * on tkwin's screen, then -1 values are returned for both + * coordinates. The argument tkwin must be a toplevel window. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkGetPointerCoords( + Tk_Window tkwin, /* Toplevel window that identifies screen + * on which lookup is to be done. */ + int *xPtr, int *yPtr) /* Store pointer coordinates here. */ +{ + Point where; + + GetMouse(&where); + LocalToGlobal(&where); + *xPtr = where.h; + *yPtr = where.v; +} + +/* + *---------------------------------------------------------------------- + * + * InitialWindowBounds -- + * + * This function calculates the initial bounds for a new Mac + * toplevel window. Unless the geometry is specified by the user + * this code will auto place the windows in a cascade diagonially + * across the main monitor of the Mac. + * + * Results: + * The bounds are returned in geometry. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +static void +InitialWindowBounds( + TkWindow *winPtr, /* Window to get initial bounds for. */ + Rect *geometry) /* On return the initial bounds. */ +{ + int x, y; + static int defaultX = 5; + static int defaultY = 45; + + if (!(winPtr->wmInfoPtr->sizeHintsFlags & (USPosition | PPosition))) { + /* + * We will override the program & hopefully place the + * window in a "better" location. + */ + BitMap screenBits; + GetQDGlobalsScreenBits(&screenBits); + if (((screenBits.bounds.right - defaultX) < 30) || + ((screenBits.bounds.bottom - defaultY) < 30)) { + defaultX = 5; + defaultY = 45; + } + x = defaultX; + y = defaultY; + defaultX += 20; + defaultY += 20; + } else { + x = winPtr->wmInfoPtr->x; + y = winPtr->wmInfoPtr->y; + } + + geometry->left = x; + geometry->top = y; + geometry->right = x + winPtr->changes.width; + geometry->bottom = y + winPtr->changes.height; +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXResizable -- + * + * This function determines if the passed in window is part of + * a toplevel window that is resizable. If the window is + * resizable in the x, y or both directions, true is returned. + * + * Results: + * True if resizable, false otherwise. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkMacOSXResizable( + TkWindow *winPtr) /* Tk window or NULL. */ +{ + WmInfo *wmPtr; + + if (winPtr == NULL) { + return false; + } + while (winPtr->wmInfoPtr == NULL) { + winPtr = winPtr->parentPtr; + } + + wmPtr = winPtr->wmInfoPtr; + if ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) && + (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE)) { + return false; + } else { + return true; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXGrowToplevel -- + * + * The function is invoked when the user clicks in the grow region + * of a Tk window. The function will handle the dragging + * procedure and not return until completed. Finally, the function + * may place information Tk's event queue is the window was resized. + * + * Results: + * True if events were placed on event queue, false otherwise. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkMacOSXGrowToplevel( + WindowRef whichWindow, + Point start) +{ + Point where = start; + TkDisplay *dispPtr; + Rect portRect; + + GlobalToLocal(&where); + GetPortBounds(GetWindowPort(whichWindow), &portRect ); + if (where.h > (portRect.right - 16) && + where.v > (portRect.bottom - 16)) { + + Window window; + TkWindow *winPtr; + WmInfo *wmPtr; + Rect bounds; + long growResult; + + window = TkMacOSXGetXWindow(whichWindow); + dispPtr = TkGetDisplayList(); + winPtr = (TkWindow *) Tk_IdToWindow(dispPtr->display, window); + wmPtr = winPtr->wmInfoPtr; + + /* TODO: handle grid size options. */ + if ((wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) && + (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE)) { + return false; + } + if (wmPtr->flags & WM_WIDTH_NOT_RESIZABLE) { + bounds.left = bounds.right = winPtr->changes.width; + } else { + bounds.left = (wmPtr->minWidth < 64) ? 64 : wmPtr->minWidth; + bounds.right = (wmPtr->maxWidth < 64) ? 64 : wmPtr->maxWidth; + } + if (wmPtr->flags & WM_HEIGHT_NOT_RESIZABLE) { + bounds.top = bounds.bottom = winPtr->changes.height; + } else { + bounds.top = (wmPtr->minHeight < 64) ? 64 : wmPtr->minHeight; + bounds.bottom = (wmPtr->maxHeight < 64) ? 64 : wmPtr->maxHeight; + } + + growResult = GrowWindow(whichWindow, start, &bounds); + + if (growResult != 0) { + SizeWindow(whichWindow, + LoWord(growResult), HiWord(growResult), true); + SetPort( GetWindowPort(whichWindow)); + InvalWindowRect(whichWindow,&portRect); /* TODO: may not be needed */ + TkMacOSXInvalClipRgns(winPtr); + TkGenWMConfigureEvent((Tk_Window) winPtr, -1, -1, + (int) LoWord(growResult), (int) HiWord(growResult), + TK_SIZE_CHANGED); + return true; + } + return false; + } + return false; +} + +/* + *---------------------------------------------------------------------- + * + * TkSetWMName -- + * + * Set the title for a toplevel window. If the window is embedded, + * do not change the window title. + * + * Results: + * None. + * + * Side effects: + * The title of the window is changed. + * + *---------------------------------------------------------------------- + */ + +void +TkSetWMName( + TkWindow *winPtr, + Tk_Uid titleUid) +{ + Str255 pTitle; + WindowRef macWin; + int destWrote; + + if (Tk_IsEmbedded(winPtr)) { + return; + } + Tcl_UtfToExternal(NULL, TkMacOSXCarbonEncoding, titleUid, + strlen(titleUid), 0, NULL, + (char *) &pTitle[1], + 255, NULL, &destWrote, NULL); /* Internalize native */ + pTitle[0] = destWrote; + + macWin = GetWindowFromPort(TkMacOSXGetDrawablePort(winPtr->window)); + + /* + * FIXME: Convert this to SetWindowTitleWithCFString, we should + * use CFStrings and not pascal strings wherever they are supported, + * since at some point there will be encodings that can't be supported + * with the pascal string interfaces. + */ + + SetWTitle( macWin, pTitle); +} + + +/* + *---------------------------------------------------------------------- + * + * TkGetTransientMaster -- + * + * If the passed window has the TRANSIENT_FOR property set this + * will return the master window. Otherwise it will return None. + * + * Results: + * The master window or None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Window +TkGetTransientMaster( + TkWindow *winPtr) +{ + if (winPtr->wmInfoPtr != NULL) { + return winPtr->wmInfoPtr->master; + } + return None; +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXGetXWindow -- + * + * Returns the X window Id associated with the given WindowRef. + * + * Results: + * The window id is returned. None is returned if not a Tk window. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +Window +TkMacOSXGetXWindow( + WindowRef macWinPtr) +{ + Tcl_HashEntry *hPtr; + + if ((macWinPtr == NULL) || !windowHashInit) { + return None; + } + hPtr = Tcl_FindHashEntry(&windowTable, (char *) macWinPtr); + if (hPtr == NULL) { + return None; + } + return (Window) Tcl_GetHashValue(hPtr); +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXZoomToplevel -- + * + * The function is invoked when the user clicks in the zoom region + * of a Tk window. The function will handle the mouse tracking + * for the interaction. If the window is to be zoomed the window + * size is changed and events are generated to let Tk know what + * happened. + * + * Results: + * True if events were placed on event queue, false otherwise. + * + * Side effects: + * The window may be resized & events placed on Tk's queue. + * + *---------------------------------------------------------------------- + */ + +int +TkMacOSXZoomToplevel( + WindowRef whichWindow, /* The Macintosh window to zoom. */ + Point where, /* The current mouse position. */ + short zoomPart) /* Either inZoomIn or inZoomOut */ +{ + Window window; + Tk_Window tkwin; + Point location = {0, 0}; + int xOffset, yOffset; + WmInfo *wmPtr; + TkDisplay *dispPtr; + Rect portRect; + + SetPort( GetWindowPort(whichWindow)); + if (!TrackBox(whichWindow, where, zoomPart)) { + return false; + } + + /* + * We should now zoom the window (as long as it's one of ours). We + * also need to generate an event to let Tk know that the window size + * has changed. + */ + window = TkMacOSXGetXWindow(whichWindow); + dispPtr = TkGetDisplayList(); + tkwin = Tk_IdToWindow(dispPtr->display, window); + if (tkwin == NULL) { + return false; + } + + /* + * The following block of code works around a bug in the window + * definition for Apple's floating windows. The zoom behavior is + * broken - we must manually set the standard state (by default + * it's something like 1x1) and we must swap the zoomPart manually + * otherwise we always get the same zoomPart and nothing happens. + */ + wmPtr = ((TkWindow *) tkwin)->wmInfoPtr; + if (wmPtr->style >= floatProc && wmPtr->style <= floatSideZoomGrowProc) { + if (zoomPart == inZoomIn) { + BitMap screenBits; + Rect zoomRect; + GetQDGlobalsScreenBits(&screenBits); + zoomRect = screenBits.bounds; + InsetRect(&zoomRect, 60, 60); + SetWindowStandardState(whichWindow, &zoomRect); + zoomPart = inZoomOut; + } else { + zoomPart = inZoomIn; + } + } else { + zoomPart = inZoomIn; + } + + ZoomWindow(whichWindow, zoomPart, false); + InvalWindowRect(whichWindow,&portRect); + TkMacOSXInvalClipRgns((TkWindow *) tkwin); + + LocalToGlobal(&location); + TkMacOSXWindowOffset(whichWindow, &xOffset, &yOffset); + location.h -= xOffset; + location.v -= yOffset; + GetPortBounds ( GetWindowPort(whichWindow), &portRect ); + TkGenWMConfigureEvent(tkwin, location.h, location.v, + portRect.right - portRect.left, + portRect.bottom - portRect.top, + TK_BOTH_CHANGED); + return true; +} + +/* + *---------------------------------------------------------------------- + * + * TkUnsupported1Cmd -- + * + * This procedure is invoked to process the + * "::tk::unsupported::MacWindowStyle" Tcl command. + * This command allows you to set the style of decoration + * for a Macintosh window. + * + * Results: + * A standard Tcl result. + * + * Side effects: + * Changes the style of a new Mac window. + * + *---------------------------------------------------------------------- + */ + + /* ARGSUSED */ +int +TkUnsupported1Cmd( + ClientData clientData, /* Main window associated with + * interpreter. */ + Tcl_Interp *interp, /* Current interpreter. */ + int argc, /* Number of arguments. */ + CONST char **argv) /* Argument strings. */ +{ + Tk_Window tkwin = (Tk_Window) clientData; + TkWindow *winPtr; + WmInfo *wmPtr; + int c; + size_t length; + + if (argc < 3) { + Tcl_AppendResult(interp, "wrong # args: should be \"", + argv[0], " option window ?arg ...?\"", (char *) NULL); + return TCL_ERROR; + } + + winPtr = (TkWindow *) Tk_NameToWindow(interp, argv[2], tkwin); + if (winPtr == NULL) { + return TCL_ERROR; + } + if (!(winPtr->flags & TK_TOP_LEVEL)) { + Tcl_AppendResult(interp, "window \"", winPtr->pathName, + "\" isn't a top-level window", (char *) NULL); + return TCL_ERROR; + } + wmPtr = winPtr->wmInfoPtr; + c = argv[1][0]; + length = strlen(argv[1]); + if ((c == 's') && (strncmp(argv[1], "style", length) == 0)) { + if ((argc < 3) || (argc > 5)) { + Tcl_AppendResult(interp, "wrong # arguments: must be \"", + argv[0], " style window ?windowStyle?\"", + " or \"", argv[0], "style window ?class attributes?\"", + (char *) NULL); + return TCL_ERROR; + } + + if (argc == 3) { + int appearanceSpec = 0; + + switch (wmPtr->style) { + case -1: + appearanceSpec = 1; + break; + case noGrowDocProc: + case documentProc: + Tcl_SetResult(interp, "documentProc", TCL_STATIC); + break; + case dBoxProc: + Tcl_SetResult(interp, "dBoxProc", TCL_STATIC); + break; + case plainDBox: + Tcl_SetResult(interp, "plainDBox", TCL_STATIC); + break; + case altDBoxProc: + Tcl_SetResult(interp, "altDBoxProc", TCL_STATIC); + break; + case movableDBoxProc: + Tcl_SetResult(interp, "movableDBoxProc", TCL_STATIC); + break; + case zoomDocProc: + case zoomNoGrow: + Tcl_SetResult(interp, "zoomDocProc", TCL_STATIC); + break; + /* Not supported in Carbon + case rDocProc: + Tcl_SetResult(interp, "rDocProc", TCL_STATIC); + break; + */ + case floatProc: + case floatGrowProc: + Tcl_SetResult(interp, "floatProc", TCL_STATIC); + break; + case floatZoomProc: + case floatZoomGrowProc: + Tcl_SetResult(interp, "floatZoomProc", TCL_STATIC); + break; + case floatSideProc: + case floatSideGrowProc: + Tcl_SetResult(interp, "floatSideProc", TCL_STATIC); + break; + case floatSideZoomProc: + case floatSideZoomGrowProc: + Tcl_SetResult(interp, "floatSideZoomProc", TCL_STATIC); + break; + default: + panic("invalid style"); + } + if (appearanceSpec) { + Tcl_Obj *attributeList, *newResult = NULL; + + switch (wmPtr->macClass) { + case kAlertWindowClass: + newResult = Tcl_NewStringObj("alert", -1); + break; + case kMovableAlertWindowClass: + newResult = Tcl_NewStringObj("moveableAlert", -1); + break; + case kModalWindowClass: + newResult = Tcl_NewStringObj("modal", -1); + break; + case kMovableModalWindowClass: + newResult = Tcl_NewStringObj("moveableModal", -1); + break; + case kFloatingWindowClass: + newResult = Tcl_NewStringObj("floating", -1); + break; + case kDocumentWindowClass: + newResult = Tcl_NewStringObj("document", -1); + break; + case kHelpWindowClass: + newResult = Tcl_NewStringObj("help", -1); + break; + case kToolbarWindowClass: + newResult = Tcl_NewStringObj("toolbar", -1); + break; + default: + panic("invalid class"); + } + + attributeList = Tcl_NewListObj(0, NULL); + if (wmPtr->attributes == kWindowNoAttributes) { + Tcl_ListObjAppendElement(interp, attributeList, + Tcl_NewStringObj("none", -1)); + } else if (wmPtr->attributes == kWindowStandardDocumentAttributes) { + Tcl_ListObjAppendElement(interp, attributeList, + Tcl_NewStringObj("standardDocument", -1)); + } else if (wmPtr->attributes == kWindowStandardFloatingAttributes) { + Tcl_ListObjAppendElement(interp, attributeList, + Tcl_NewStringObj("standardFloating", -1)); + } else { + if (wmPtr->attributes & kWindowCloseBoxAttribute) { + Tcl_ListObjAppendElement(interp, attributeList, + Tcl_NewStringObj("closeBox", -1)); + } + if (wmPtr->attributes & kWindowHorizontalZoomAttribute) { + Tcl_ListObjAppendElement(interp, attributeList, + Tcl_NewStringObj("horizontalZoom", -1)); + } + if (wmPtr->attributes & kWindowVerticalZoomAttribute) { + Tcl_ListObjAppendElement(interp, attributeList, + Tcl_NewStringObj("verticalZoom", -1)); + } + if (wmPtr->attributes & kWindowCollapseBoxAttribute) { + Tcl_ListObjAppendElement(interp, attributeList, + Tcl_NewStringObj("collapseBox", -1)); + } + if (wmPtr->attributes & kWindowResizableAttribute) { + Tcl_ListObjAppendElement(interp, attributeList, + Tcl_NewStringObj("resizable", -1)); + } + if (wmPtr->attributes & kWindowSideTitlebarAttribute) { + Tcl_ListObjAppendElement(interp, attributeList, + Tcl_NewStringObj("sideTitlebar", -1)); + } + if (wmPtr->attributes & kWindowNoUpdatesAttribute) { + Tcl_ListObjAppendElement(interp, attributeList, + Tcl_NewStringObj("noUpdates", -1)); + } + if (wmPtr->attributes & kWindowNoActivatesAttribute) { + Tcl_ListObjAppendElement(interp, attributeList, + Tcl_NewStringObj("noActivates", -1)); + } + } + Tcl_ListObjAppendElement(interp, newResult, attributeList); + Tcl_SetObjResult(interp, newResult); + } + return TCL_OK; + } else if (argc == 4) { + if (strcmp(argv[3], "documentProc") == 0) { + wmPtr->style = documentProc; + } else if (strcmp(argv[3], "noGrowDocProc") == 0) { + wmPtr->style = documentProc; + } else if (strcmp(argv[3], "dBoxProc") == 0) { + wmPtr->style = dBoxProc; + } else if (strcmp(argv[3], "plainDBox") == 0) { + wmPtr->style = plainDBox; + } else if (strcmp(argv[3], "altDBoxProc") == 0) { + wmPtr->style = altDBoxProc; + } else if (strcmp(argv[3], "movableDBoxProc") == 0) { + wmPtr->style = movableDBoxProc; + } else if (strcmp(argv[3], "zoomDocProc") == 0) { + wmPtr->style = zoomDocProc; + } else if (strcmp(argv[3], "zoomNoGrow") == 0) { + wmPtr->style = zoomNoGrow; + } + /* + else + if (strcmp(argv[3], "rDocProc") == 0) { + wmPtr->style = rDocProc; + } + */ + else if (strcmp(argv[3], "floatProc") == 0) { + wmPtr->style = floatGrowProc; + } else if (strcmp(argv[3], "floatGrowProc") == 0) { + wmPtr->style = floatGrowProc; + } else if (strcmp(argv[3], "floatZoomProc") == 0) { + wmPtr->style = floatZoomGrowProc; + } else if (strcmp(argv[3], "floatZoomGrowProc") == 0) { + wmPtr->style = floatZoomGrowProc; + } else if (strcmp(argv[3], "floatSideProc") == 0) { + wmPtr->style = floatSideGrowProc; + } else if (strcmp(argv[3], "floatSideGrowProc") == 0) { + wmPtr->style = floatSideGrowProc; + } else if (strcmp(argv[3], "floatSideZoomProc") == 0) { + wmPtr->style = floatSideZoomGrowProc; + } else if (strcmp(argv[3], "floatSideZoomGrowProc") == 0) { + wmPtr->style = floatSideZoomGrowProc; + } else { + Tcl_AppendResult(interp, "bad style: should be documentProc, ", + "dBoxProc, plainDBox, altDBoxProc, movableDBoxProc, ", + "zoomDocProc, rDocProc, floatProc, floatZoomProc, ", + "floatSideProc, or floatSideZoomProc", + (char *) NULL); + return TCL_ERROR; + } + } else if (argc == 5) { + int oldClass = wmPtr->macClass; + int oldAttributes = wmPtr->attributes; + + if (strcmp(argv[3], "alert") == 0) { + wmPtr->macClass = kAlertWindowClass; + } else if (strcmp(argv[3], "moveableAlert") == 0) { + wmPtr->macClass = kMovableAlertWindowClass; + } else if (strcmp(argv[3], "modal") == 0) { + wmPtr->macClass = kModalWindowClass; + } else if (strcmp(argv[3], "moveableModal") == 0) { + wmPtr->macClass = kMovableModalWindowClass; + } else if (strcmp(argv[3], "floating") == 0) { + wmPtr->macClass = kFloatingWindowClass; + } else if (strcmp(argv[3], "document") == 0) { + wmPtr->macClass = kDocumentWindowClass; + } else if (strcmp(argv[3], "help") == 0) { + wmPtr->macClass = kHelpWindowClass; + } else if (strcmp(argv[3], "toolbar") == 0) { + wmPtr->macClass = kToolbarWindowClass; + } else { + wmPtr->macClass = oldClass; + Tcl_AppendResult(interp, "bad class: should be alert, ", + "moveableAlert, modal, moveableModal, floating, ", + "help, or document", + (char *) NULL); + return TCL_ERROR; + } + + if (strcmp(argv[4], "none") == 0) { + wmPtr->attributes = kWindowNoAttributes; + } else if (strcmp(argv[4], "standardDocument") == 0) { + wmPtr->attributes = kWindowStandardDocumentAttributes; + } else if (strcmp(argv[4], "standardFloating") == 0) { + wmPtr->attributes = kWindowStandardFloatingAttributes; + } else { + int foundOne = 0; + int attrArgc, i; + CONST char **attrArgv = NULL; + + if (Tcl_SplitList(interp, argv[4], &attrArgc, &attrArgv) != TCL_OK) { + wmPtr->macClass = oldClass; + Tcl_AppendResult(interp, "Ill-formed attributes list: \"", + argv[4], "\".", (char *) NULL); + return TCL_ERROR; + } + + wmPtr->attributes = kWindowNoAttributes; + + for (i = 0; i < attrArgc; i++) { + if ((*attrArgv[i] == 'c') + && (strcmp(attrArgv[i], "closeBox") == 0)) { + wmPtr->attributes |= kWindowCloseBoxAttribute; + foundOne = 1; + } else if ((*attrArgv[i] == 'h') + && (strcmp(attrArgv[i], "horizontalZoom") == 0)) { + wmPtr->attributes |= kWindowHorizontalZoomAttribute; + foundOne = 1; + } else if ((*attrArgv[i] == 'v') + && (strcmp(attrArgv[i], "verticalZoom") == 0)) { + wmPtr->attributes |= kWindowVerticalZoomAttribute; + foundOne = 1; + } else if ((*attrArgv[i] == 'c') + && (strcmp(attrArgv[i], "collapseBox") == 0)) { + wmPtr->attributes |= kWindowCollapseBoxAttribute; + foundOne = 1; + } else if ((*attrArgv[i] == 'r') + && (strcmp(attrArgv[i], "resizable") == 0)) { + wmPtr->attributes |= kWindowResizableAttribute; + foundOne = 1; + } else if ((*attrArgv[i] == 's') + && (strcmp(attrArgv[i], "sideTitlebar") == 0)) { + wmPtr->attributes |= kWindowSideTitlebarAttribute; + foundOne = 1; + } else { + foundOne = 0; + break; + } + } + + if (attrArgv != NULL) { + ckfree ((char *) attrArgv); + } + + if (foundOne != 1) { + wmPtr->macClass = oldClass; + wmPtr->attributes = oldAttributes; + + Tcl_AppendResult(interp, "bad attribute: \"", argv[4], + "\", should be standardDocument, ", + "standardFloating, or some combination of ", + "closeBox, horizontalZoom, verticalZoom, ", + "collapseBox, resizable, or sideTitlebar.", + (char *) NULL); + return TCL_ERROR; + } + } + + wmPtr->style = -1; + } + } else { + Tcl_AppendResult(interp, "unknown or ambiguous option \"", argv[1], + "\": must be style", + (char *) NULL); + return TCL_ERROR; + } + + return TCL_OK; +} + +/* + *---------------------------------------------------------------------- + * + * TkpMakeMenuWindow -- + * + * Configure the window to be either a undecorated pull-down + * (or pop-up) menu, or as a toplevel floating menu (palette). + * + * Results: + * None. + * + * Side effects: + * Changes the style bit used to create a new Mac toplevel. + * + *---------------------------------------------------------------------- + */ + +void +TkpMakeMenuWindow( + Tk_Window tkwin, /* New window. */ + int transient) /* 1 means menu is only posted briefly as + * a popup or pulldown or cascade. 0 means + * menu is always visible, e.g. as a + * floating menu. */ +{ + if (transient) { + ((TkWindow *) tkwin)->wmInfoPtr->style = plainDBox; + } else { + ((TkWindow *) tkwin)->wmInfoPtr->style = floatProc; + ((TkWindow *) tkwin)->wmInfoPtr->flags |= WM_WIDTH_NOT_RESIZABLE; + ((TkWindow *) tkwin)->wmInfoPtr->flags |= WM_HEIGHT_NOT_RESIZABLE; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXMakeRealWindowExist -- + * + * This function finally creates the real Macintosh window that + * the Mac actually understands. + * + * Results: + * None. + * + * Side effects: + * A new Macintosh toplevel is created. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXMakeRealWindowExist( + TkWindow *winPtr) /* Tk window. */ +{ + WmInfo *wmPtr = winPtr->wmInfoPtr; + WindowRef newWindow = NULL; + ControlRef rootControl = NULL; + MacDrawable *macWin; + Rect geometry = {0,0,0,0}; + Tcl_HashEntry *valueHashPtr; + int new; + TkMacOSXWindowList *listPtr; + + if (TkMacOSXHostToplevelExists(winPtr)) { + return; + } + + macWin = (MacDrawable *) winPtr->window; + + /* + * If this is embedded, make sure its container's toplevel exists, + * then return... + */ + + if (Tk_IsEmbedded(winPtr)) { + TkWindow *contWinPtr; + + contWinPtr = TkpGetOtherWindow(winPtr); + if (contWinPtr != NULL) { + TkMacOSXMakeRealWindowExist(contWinPtr->privatePtr->toplevel->winPtr); + macWin->flags |= TK_HOST_EXISTS; + return; + } else if (gMacEmbedHandler != NULL) { + if (gMacEmbedHandler->containerExistProc != NULL) { + if (gMacEmbedHandler->containerExistProc((Tk_Window) winPtr) != TCL_OK) { + panic("ContainerExistProc could not make container"); + } + } + return; + } else { + panic("TkMacOSXMakeRealWindowExist could not find container"); + } + + /* + * NOTE: Here we should handle out of process embedding. + */ + + } + + InitialWindowBounds(winPtr, &geometry); + + if (wmPtr->style == -1) { + OSStatus err; + /* + * There seems to be a bug in CreateNewWindow: If I set the + * window geometry to be the too small for the structure region, + * then the whole window is positioned incorrectly. + * Adding this here makes the positioning work, and the size will + * get overwritten when you actually map the contents of the window. + */ + + geometry.right += 64; + geometry.bottom += 24; + err = CreateNewWindow(wmPtr->macClass, wmPtr->attributes, + &geometry, &newWindow); + if (err != noErr) { + newWindow = NULL; + } + + } else { + newWindow = NewCWindow(NULL, &geometry, "\ptemp", false, + (short) wmPtr->style, (WindowRef) -1, true, 0); + } + + if (newWindow == NULL) { + panic("couldn't allocate new Mac window"); + } + if (CreateRootControl(newWindow,&rootControl) != noErr ) { + panic("couldn't create root control for new Mac window"); + } + + /* + * Add this window to the list of toplevel windows. + */ + + listPtr = (TkMacOSXWindowList *) ckalloc(sizeof(TkMacOSXWindowList)); + listPtr->nextPtr = tkMacOSXWindowListPtr; + listPtr->winPtr = winPtr; + tkMacOSXWindowListPtr = listPtr; + + macWin->grafPtr = GetWindowPort ( newWindow ); + macWin->rootControl = rootControl; + MoveWindowStructure(newWindow, geometry.left, geometry.top); + SetPort(GetWindowPort(newWindow)); + + if (!windowHashInit) { + Tcl_InitHashTable(&windowTable, TCL_ONE_WORD_KEYS); + windowHashInit = true; + } + valueHashPtr = Tcl_CreateHashEntry(&windowTable, + (char *) newWindow, &new); + if (!new) { + panic("same macintosh window allocated twice!"); + } + Tcl_SetHashValue(valueHashPtr, macWin); + + macWin->flags |= TK_HOST_EXISTS; +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXRegisterOffScreenWindow -- + * + * This function adds the passed in Off Screen Port to the + * hash table that maps Mac windows to root X windows. + * + * FIXME: This is not currently used. Is there any reason + * to keep it? + * + * Results: + * None. + * + * Side effects: + * An entry is added to the windowTable hash table. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXRegisterOffScreenWindow( + Window window, /* Window structure. */ + GWorldPtr portPtr) /* Pointer to a Mac GWorld. */ +{ + MacDrawable *macWin; + Tcl_HashEntry *valueHashPtr; + int new; + + macWin = (MacDrawable *) window; + if (!windowHashInit) { + Tcl_InitHashTable(&windowTable, TCL_ONE_WORD_KEYS); + windowHashInit = true; + } + valueHashPtr = Tcl_CreateHashEntry(&windowTable, + (char *) portPtr, &new); + if (!new) { + panic("same macintosh window allocated twice!"); + } + Tcl_SetHashValue(valueHashPtr, macWin); +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXUnregisterMacWindow -- + * + * Given a macintosh port window, this function removes the + * association between this window and the root X window that + * Tk cares about. + * + * Results: + * None. + * + * Side effects: + * An entry is removed from the windowTable hash table. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXUnregisterMacWindow( + WindowRef macWinPtr) /* Reference to a Mac Window */ +{ + Tcl_HashEntry *entryPtr; + if (!windowHashInit) { + panic("TkMacOSXUnregisterMacWindow: unmapping before inited"); + } + entryPtr=Tcl_FindHashEntry(&windowTable,(char *) macWinPtr); + if (!entryPtr) { + fprintf(stderr,"Unregister:failed to find window %08x\n", + (int) macWinPtr ); + } + else { + Tcl_DeleteHashEntry(entryPtr); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXSetScrollbarGrow -- + * + * Sets a flag for a toplevel window indicating that the passed + * Tk scrollbar window will display the grow region for the + * toplevel window. + * + * Results: + * None. + * + * Side effects: + * A flag is set int windows toplevel parent. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXSetScrollbarGrow( + TkWindow *winPtr, /* Tk scrollbar window. */ + int flag) /* Boolean value true or false. */ +{ + if (flag) { + winPtr->privatePtr->toplevel->flags |= TK_SCROLLBAR_GROW; + winPtr->privatePtr->toplevel->winPtr->wmInfoPtr->scrollWinPtr = winPtr; + } else if (winPtr->privatePtr->toplevel->winPtr->wmInfoPtr->scrollWinPtr + == winPtr) { + winPtr->privatePtr->toplevel->flags &= ~TK_SCROLLBAR_GROW; + winPtr->privatePtr->toplevel->winPtr->wmInfoPtr->scrollWinPtr = NULL; + } +} + +/* + *---------------------------------------------------------------------- + * + * TkWmFocusToplevel -- + * + * This is a utility procedure invoked by focus-management code. It + * exists because of the extra wrapper windows that exist under + * Unix; its job is to map from wrapper windows to the + * corresponding toplevel windows. On PCs and Macs there are no + * wrapper windows so no mapping is necessary; this procedure just + * determines whether a window is a toplevel or not. + * + * Results: + * If winPtr is a toplevel window, returns the pointer to the + * window; otherwise returns NULL. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TkWindow * +TkWmFocusToplevel( + TkWindow *winPtr) /* Window that received a focus-related + * event. */ +{ + if (!(winPtr->flags & TK_TOP_LEVEL)) { + return NULL; + } + return winPtr; +} + +/* + *---------------------------------------------------------------------- + * + * TkpGetWrapperWindow -- + * + * This is a utility procedure invoked by focus-management code. It + * maps to the wrapper for a top-level, which is just the same + * as the top-level on Macs and PCs. + * + * Results: + * If winPtr is a toplevel window, returns the pointer to the + * window; otherwise returns NULL. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TkWindow * +TkpGetWrapperWindow( + TkWindow *winPtr) /* Window that received a focus-related + * event. */ +{ + if (!(winPtr->flags & TK_TOP_LEVEL)) { + return NULL; + } + return winPtr; +} + +/* + *---------------------------------------------------------------------- + * + * TkpWmSetState -- + * + * Sets the window manager state for the wrapper window of a + * given toplevel window. + * + * Results: + * None. + * + * Side effects: + * May maximize, minimize, restore, or withdraw a window. + * + *---------------------------------------------------------------------- + */ + +void +TkpWmSetState(winPtr, state) + TkWindow *winPtr; /* Toplevel window to operate on. */ + int state; /* One of IconicState, ZoomState, NormalState, + * or WithdrawnState. */ +{ + WmInfo *wmPtr = winPtr->wmInfoPtr; + WindowRef macWin; + + wmPtr->hints.initial_state = state; + if (wmPtr->flags & WM_NEVER_MAPPED) { + return; + } + + macWin = GetWindowFromPort(TkMacOSXGetDrawablePort (winPtr->window)); + + if (state == WithdrawnState) { + Tk_UnmapWindow((Tk_Window) winPtr); + } else if (state == IconicState) { + Tk_UnmapWindow((Tk_Window) winPtr); + /* + * The window always gets unmapped. However, if we can show the + * icon version of the window (collapsed) we make the window visable + * and then collapse it. + * + * TODO: This approach causes flashing! + */ + + if (IsWindowCollapsable(macWin)) { + ShowWindow(macWin); + CollapseWindow( macWin, true); + } + + } else if (state == NormalState) { + Tk_MapWindow((Tk_Window) winPtr); + CollapseWindow((WindowPtr) macWin, false); + } else if (state == ZoomState) { + /* TODO: need to support zoomed windows */ + } +} + +/* + *---------------------------------------------------------------------- + * + * TkpIsWindowFloating -- + * + * Returns 1 if a window is floating, 0 otherwise. + * + * Results: + * 1 or 0 depending on window's floating attribute. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkpIsWindowFloating(WindowRef wRef) +{ + WindowClass class; + GetWindowClass(wRef, &class); + return (class == kFloatingWindowClass); +} + +/* + *---------------------------------------------------------------------- + * + * TkMacOSXWindowOffset -- + * + * Determines the x and y offset from the orgin of the toplevel + * window dressing (the structure region, ie. title bar) and the + * orgin of the content area. + * + * Results: + * The x & y offset in pixels. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkMacOSXWindowOffset( + WindowRef wRef, + int *xOffset, + int *yOffset) +{ + OSErr err = noErr; + static RgnHandle strucRgn = NULL; + static RgnHandle contRgn = NULL; + Rect strucRect, contRect; + + if (!strucRgn) { + if(!(strucRgn = NewRgn())) { + err=MemError(); + } + } + if (!contRgn) { + if(!(contRgn = NewRgn())) { + err=MemError(); + } + } + if (err==noErr) { + GetWindowRegion(wRef, kWindowStructureRgn, strucRgn); + GetWindowRegion(wRef, kWindowContentRgn, contRgn); + GetRegionBounds(strucRgn,&strucRect); + GetRegionBounds(contRgn,&contRect); + *xOffset = contRect.left - strucRect.left; + *yOffset = contRect.top - strucRect.top; + } else { + *xOffset = 0; + *yOffset = 0; + } + return; +} + +/* + *---------------------------------------------------------------------- + * + * TkpGetMS -- + * + * Return a relative time in milliseconds. It doesn't matter + * when the epoch was. + * + * Results: + * Number of milliseconds. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +unsigned long +TkpGetMS() +{ + long long * int64Ptr; + UnsignedWide micros; + + Microseconds(µs); + int64Ptr = (long long *) µs; + + /* + * We need 64 bit math to do this. This is available in CW 11 + * and on. Other's will need to use a different scheme. + */ + + *int64Ptr /= 1000; + + return (long) *int64Ptr; +} + +/* + *---------------------------------------------------------------------- + * + * XSetInputFocus -- + * + * Change the focus window for the application. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +XSetInputFocus( + Display* display, + Window focus, + int revert_to, + Time time) +{ + /* + * Don't need to do a thing. Tk manages the focus for us. + */ +} + +/* + *---------------------------------------------------------------------- + * + * TkpChangeFocus -- + * + * This procedure is a stub on the Mac because we always own the + * focus if we are a front most application. + * + * Results: + * The return value is the serial number of the command that + * changed the focus. It may be needed by the caller to filter + * out focus change events that were queued before the command. + * If the procedure doesn't actually change the focus then + * it returns 0. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkpChangeFocus(winPtr, force) + TkWindow *winPtr; /* Window that is to receive the X focus. */ + int force; /* Non-zero means claim the focus even + * if it didn't originally belong to + * topLevelPtr's application. */ +{ + /* + * We don't really need to do anything on the Mac. Tk will + * keep all this state for us. + */ + + if (winPtr->atts.override_redirect) { + return 0; + } + + /* + * Remember the current serial number for the X server and issue + * a dummy server request. This marks the position at which we + * changed the focus, so we can distinguish FocusIn and FocusOut + * events on either side of the mark. + */ + + return NextRequest(winPtr->display); +} + + +/* + *---------------------------------------------------------------------- + * + * TkWmStackorderToplevelWrapperMap -- + * + * This procedure will create a table that maps the reparent wrapper + * X id for a toplevel to the TkWindow structure that is wraps. + * Tk keeps track of a mapping from the window X id to the TkWindow + * structure but that does us no good here since we only get the X + * id of the wrapper window. Only those toplevel windows that are + * mapped have a position in the stacking order. + * + * + * Results: + * None. + * + * Side effects: + * Adds entries to the passed hashtable. + * + *---------------------------------------------------------------------- + */ +void +TkWmStackorderToplevelWrapperMap(winPtr, table) + TkWindow *winPtr; /* TkWindow to recurse on */ + Tcl_HashTable *table; /* Maps mac window to TkWindow */ +{ + TkWindow *childPtr; + Tcl_HashEntry *hPtr; + void *wrapper; + int newEntry; + + if (Tk_IsMapped(winPtr) && Tk_IsTopLevel(winPtr)) { + wrapper = (void *) TkMacOSXGetDrawablePort(winPtr->window); + + hPtr = Tcl_CreateHashEntry(table, + (char *) wrapper, &newEntry); + Tcl_SetHashValue(hPtr, winPtr); + } + + for (childPtr = winPtr->childList; childPtr != NULL; + childPtr = childPtr->nextPtr) { + TkWmStackorderToplevelWrapperMap(childPtr, table); + } +} + +/* + *---------------------------------------------------------------------- + * + * TkWmStackorderToplevel -- + * + * This procedure returns the stack order of toplevel windows. + * + * Results: + * An array of pointers to tk window objects in stacking order + * or else NULL if there was an error. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +TkWindow ** +TkWmStackorderToplevel(parentPtr) + TkWindow *parentPtr; /* Parent toplevel window. */ +{ + WindowRef frontWindow; + TkWindow *childWinPtr, **windows, **window_ptr; + Tcl_HashTable table; + Tcl_HashEntry *hPtr; + Tcl_HashSearch search; + + /* + * Map mac windows to a TkWindow of the wrapped toplevel. + */ + + Tcl_InitHashTable(&table, TCL_ONE_WORD_KEYS); + TkWmStackorderToplevelWrapperMap(parentPtr, &table); + + windows = (TkWindow **) ckalloc((table.numEntries+1) + * sizeof(TkWindow *)); + + /* + * Special cases: If zero or one toplevels were mapped + * there is no need to enumerate Windows. + */ + + switch (table.numEntries) { + case 0: + windows[0] = NULL; + goto done; + case 1: + hPtr = Tcl_FirstHashEntry(&table, &search); + windows[0] = (TkWindow *) Tcl_GetHashValue(hPtr); + windows[1] = NULL; + goto done; + } + + frontWindow = (WindowRef) FrontWindow(); + + if (frontWindow == NULL) { + ckfree((char *) windows); + windows = NULL; + } else { + window_ptr = windows + table.numEntries; + *window_ptr-- = NULL; + while (frontWindow != NULL) { + hPtr = Tcl_FindHashEntry(&table, (char *) frontWindow); + if (hPtr != NULL) { + childWinPtr = (TkWindow *) Tcl_GetHashValue(hPtr); + *window_ptr-- = childWinPtr; + } + frontWindow = GetNextWindow(frontWindow); + } + if (window_ptr != (windows-1)) + panic("num matched toplevel windows does not equal num children"); + } + + done: + Tcl_DeleteHashTable(&table); + return windows; +} + + + + + diff --git a/macosx/tkMacOSXWm.h b/macosx/tkMacOSXWm.h new file mode 100644 index 0000000..eaa0dd5 --- /dev/null +++ b/macosx/tkMacOSXWm.h @@ -0,0 +1,302 @@ +/* +/* + * tkMacOSXWm.h -- + * + * Declarations of Macintosh specific functions for implementing the + * Mac OS X Notifier. + * + * Copyright 2001, Apple Computer, Inc. + * + * 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. + */ + +#ifndef _TKMACWM +#define _TKMACWM + +#include <Carbon/Carbon.h> +#include "tkPort.h" +#include "tkInt.h" +#include "tkMacOSXInt.h" +#include <errno.h> +#include "tkScrollbar.h" + +/* + * A data structure of the following type holds information for + * each window manager protocol (such as WM_DELETE_WINDOW) for + * which a handler (i.e. a Tcl command) has been defined for a + * particular top-level window. + */ + +typedef struct ProtocolHandler { + Atom protocol; /* Identifies the protocol. */ + struct ProtocolHandler *nextPtr; + /* Next in list of protocol handlers for + * the same top-level window, or NULL for + * end of list. */ + Tcl_Interp *interp; /* Interpreter in which to invoke command. */ + char command[4]; /* Tcl command to invoke when a client + * message for this protocol arrives. + * The actual size of the structure varies + * to accommodate the needs of the actual + * command. THIS MUST BE THE LAST FIELD OF + * THE STRUCTURE. */ +} ProtocolHandler; + +#define HANDLER_SIZE(cmdLength) \ +((unsigned) (sizeof(ProtocolHandler) - 3 + cmdLength)) + +/* + * A data structure of the following type holds window-manager-related + * information for each top-level window in an application. + */ + +typedef struct TkWmInfo { + TkWindow *winPtr; /* Pointer to main Tk information for + * this window. */ + Window reparent; /* If the window has been reparented, this + * gives the ID of the ancestor of the window + * that is a child of the root window (may + * not be window's immediate parent). If + * the window isn't reparented, this has the + * value None. */ + Tk_Uid titleUid; /* Title to display in window caption. If + * NULL, use name of widget. */ + char *iconName; /* Name to display in icon. */ + Window master; /* Master window for TRANSIENT_FOR property, + * or None. */ + XWMHints hints; /* Various pieces of information for + * window manager. */ + char *leaderName; /* Path name of leader of window group + * (corresponds to hints.window_group). + * Malloc-ed. Note: this field doesn't + * get updated if leader is destroyed. */ + char *masterWindowName; /* Path name of window specified as master + * in "wm transient" command, or NULL. + * Malloc-ed. Note: this field doesn't + * get updated if masterWindowName is + * destroyed. */ + Tk_Window icon; /* Window to use as icon for this window, + * or NULL. */ + Tk_Window iconFor; /* Window for which this window is icon, or + * NULL if this isn't an icon for anyone. */ + + /* + * Information used to construct an XSizeHints structure for + * the window manager: + */ + + int sizeHintsFlags; /* Flags word for XSizeHints structure. + * If the PBaseSize flag is set then the + * window is gridded; otherwise it isn't + * gridded. */ + int minWidth, minHeight; /* Minimum dimensions of window, in + * grid units, not pixels. */ + int maxWidth, maxHeight; /* Maximum dimensions of window, in + * grid units, not pixels. */ + Tk_Window gridWin; /* Identifies the window that controls + * gridding for this top-level, or NULL if + * the top-level isn't currently gridded. */ + int widthInc, heightInc; /* Increments for size changes (# pixels + * per step). */ + struct { + int x; /* numerator */ + int y; /* denominator */ + } minAspect, maxAspect; /* Min/max aspect ratios for window. */ + int reqGridWidth, reqGridHeight; + /* The dimensions of the window (in + * grid units) requested through + * the geometry manager. */ + int gravity; /* Desired window gravity. */ + + /* + * Information used to manage the size and location of a window. + */ + + int width, height; /* Desired dimensions of window, specified + * in grid units. These values are + * set by the "wm geometry" command and by + * ConfigureNotify events (for when wm + * resizes window). -1 means user hasn't + * requested dimensions. */ + int x, y; /* Desired X and Y coordinates for window. + * These values are set by "wm geometry", + * plus by ConfigureNotify events (when wm + * moves window). These numbers are + * different than the numbers stored in + * winPtr->changes because (a) they could be + * measured from the right or bottom edge + * of the screen (see WM_NEGATIVE_X and + * WM_NEGATIVE_Y flags) and (b) if the window + * has been reparented then they refer to the + * parent rather than the window itself. */ + int parentWidth, parentHeight; + /* Width and height of reparent, in pixels + * *including border*. If window hasn't been + * reparented then these will be the outer + * dimensions of the window, including + * border. */ + int xInParent, yInParent; /* Offset of window within reparent, measured + * from upper-left outer corner of parent's + * border to upper-left outer corner of child's + * border. If not reparented then these are + * zero. */ + int configWidth, configHeight; + /* Dimensions passed to last request that we + * issued to change geometry of window. Used + * to eliminate redundant resize operations. */ + + /* + * Information about the virtual root window for this top-level, + * if there is one. + */ + + Window vRoot; /* Virtual root window for this top-level, + * or None if there is no virtual root + * window (i.e. just use the screen's root). */ + int vRootX, vRootY; /* Position of the virtual root inside the + * root window. If the WM_VROOT_OFFSET_STALE + * flag is set then this information may be + * incorrect and needs to be refreshed from + * the X server. If vRoot is None then these + * values are both 0. */ + unsigned int vRootWidth, vRootHeight; + /* Dimensions of the virtual root window. + * If vRoot is None, gives the dimensions + * of the containing screen. This information + * is never stale, even though vRootX and + * vRootY can be. */ + + /* + * List of children of the toplevel which have private colormaps. + */ + + TkWindow **cmapList; /* Array of window with private colormaps. */ + int cmapCount; /* Number of windows in array. */ + + /* + * Miscellaneous information. + */ + + ProtocolHandler *protPtr; /* First in list of protocol handlers for + * this window (NULL means none). */ + int cmdArgc; /* Number of elements in cmdArgv below. */ + CONST char **cmdArgv; /* Array of strings to store in the + * WM_COMMAND property. NULL means nothing + * available. */ + char *clientMachine; /* String to store in WM_CLIENT_MACHINE + * property, or NULL. */ + int flags; /* Miscellaneous flags, defined below. */ + + /* + * Macintosh information. + */ + int style; /* Native window style. */ + int macClass; + int attributes; + TkWindow *scrollWinPtr; /* Ptr to scrollbar handling grow widget. */ +} WmInfo; + + +/* + * Flag values for WmInfo structures: + * + * WM_NEVER_MAPPED - non-zero means window has never been + * mapped; need to update all info when + * window is first mapped. + * WM_UPDATE_PENDING - non-zero means a call to UpdateGeometryInfo + * has already been scheduled for this + * window; no need to schedule another one. + * WM_NEGATIVE_X - non-zero means x-coordinate is measured in + * pixels from right edge of screen, rather + * than from left edge. + * WM_NEGATIVE_Y - non-zero means y-coordinate is measured in + * pixels up from bottom of screen, rather than + * down from top. + * WM_UPDATE_SIZE_HINTS - non-zero means that new size hints need to be + * propagated to window manager. + * WM_SYNC_PENDING - set to non-zero while waiting for the window + * manager to respond to some state change. + * WM_VROOT_OFFSET_STALE - non-zero means that (x,y) offset information + * about the virtual root window is stale and + * needs to be fetched fresh from the X server. + * WM_ABOUT_TO_MAP - non-zero means that the window is about to + * be mapped by TkWmMapWindow. This is used + * by UpdateGeometryInfo to modify its behavior. + * WM_MOVE_PENDING - non-zero means the application has requested + * a new position for the window, but it hasn't + * been reflected through the window manager + * yet. + * WM_COLORMAPS_EXPLICIT - non-zero means the colormap windows were + * set explicitly via "wm colormapwindows". + * WM_ADDED_TOPLEVEL_COLORMAP - non-zero means that when "wm colormapwindows" + * was called the top-level itself wasn't + * specified, so we added it implicitly at + * the end of the list. + * WM_WIDTH_NOT_RESIZABLE - non-zero means that we're not supposed to + * allow the user to change the width of the + * window (controlled by "wm resizable" + * command). + * WM_HEIGHT_NOT_RESIZABLE - non-zero means that we're not supposed to + * allow the user to change the height of the + * window (controlled by "wm resizable" + * command). + */ + +#define WM_NEVER_MAPPED 1 +#define WM_UPDATE_PENDING 2 +#define WM_NEGATIVE_X 4 +#define WM_NEGATIVE_Y 8 +#define WM_UPDATE_SIZE_HINTS 0x10 +#define WM_SYNC_PENDING 0x20 +#define WM_VROOT_OFFSET_STALE 0x40 +#define WM_ABOUT_TO_MAP 0x100 +#define WM_MOVE_PENDING 0x200 +#define WM_COLORMAPS_EXPLICIT 0x400 +#define WM_ADDED_TOPLEVEL_COLORMAP 0x800 +#define WM_WIDTH_NOT_RESIZABLE 0x1000 +#define WM_HEIGHT_NOT_RESIZABLE 0x2000 + +#endif + diff --git a/macosx/tkMacOSXXCursors.r b/macosx/tkMacOSXXCursors.r new file mode 100644 index 0000000..fd2a61c --- /dev/null +++ b/macosx/tkMacOSXXCursors.r @@ -0,0 +1,961 @@ +/* + * tkMacOSXXCursors.r -- + * + * This file defines a set of Macintosh cursor resources that + * emulate the X cursor set. All of these cursors were + * constructed and donated by Grant Neufeld. (gneufeld@ccs.carleton.ca) + * + * + * 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: tkMacOSXXCursors.r,v 1.2 2002/08/31 06:12:31 das Exp $ + */ + +/* + * All of the X cursors are defined as 'CURS' resources. However, a + * subset of the X cursors are also defined as 'crsr' resources. Tk + * will attempt to first use the color cursors ('crsr') if it doesn't + * exist it will attempt to use the black & white cursor ('CURS'). + */ + +data 'CURS' (3000, "X_cursor") { + $"E007 F00F F81F 7C3E 3E7C 1FF8 0FF0 07E0" + $"07E0 0FF0 1FF8 3E7C 7C3E F81F F00F E007" + $"0000 6006 700E 381C 1C38 0E70 07E0 03C0" + $"03C0 07E0 0E70 1C38 381C 700E 6006 0000" + $"0007 0007" +}; + +data 'CURS' (3001, "arrow") { + $"0000 0006 001E 007C 01FC 07F8 00F8 01F0" + $"03B0 0720 0E20 1C00 3800 7000 2000 0000" + $"0007 001F 007F 01FE 07FE 1FFC 7FFC 03F8" + $"07F8 0FF0 1F70 3E60 7C60 F840 7040 2000" + $"0001 000E" +}; + +data 'CURS' (3002, "based_arrow_down") { + $"0000 0000 0000 1FE0 0000 1FE0 0300 0300" + $"0300 0B40 0780 0300 0000 0000 0000 0000" + $"0000 0000 0000 1FE0 0000 1FE0 0780 0780" + $"3FF0 1FE0 0FC0 0780 0300 0000 0000 0000" + $"000B 0006" +}; + +data 'CURS' (3003, "based_arrow_up") { + $"0000 0000 0000 0000 0300 0780 0B40 0300" + $"0300 0300 1FE0 0000 1FE0 0000 0000 0000" + $"0000 0000 0000 0300 0780 0FC0 1FE0 3FF0" + $"0780 0780 1FE0 0000 1FE0 0000 0000 0000" + $"0004 0006" +}; + +data 'CURS' (3004, "boat") { + $"0000 0000 0000 0000 0100 03C0 8460 FFFF" + $"0018 0020 0040 FFC0 0000 0000 0000 0000" + $"0000 0000 0000 0000 0100 03C0 87E0 FFFF" + $"FFF8 FFE0 FFC0 FFC0 0000 0000 0000 0000" + $"0007 000F" +}; + +data 'CURS' (3005, "bogosity") { + $"0000 711C 1110 1110 1110 7FFC 5114 5114" + $"5114 5114 7FFC 1110 1110 1110 711C 0000" + $"0000 0000 0000 0000 0000 7FFC 7FFC 7FFC" + $"7FFC 7FFC 7FFC 0000 0000 0000 0000 0000" + $"0001 0007" +}; + +data 'CURS' (3006, "bottom_left_corner") { + $"0000 0000 0000 0000 C000 C020 C840 C880" + $"C900 CA00 CC00 CFC0 C000 C000 FFF0 FFF0" + $"0000 0000 0000 0000 0000 0020 0840 0880" + $"0900 0A00 0C00 0FC0 0000 0000 0000 0000" + $"000F 0000" +}; + +data 'CURS' (3007, "bottom_right_corner") { + $"0000 0000 0000 0000 0003 0403 0213 0113" + $"0093 0053 0033 03F3 0003 0003 0FFF 0FFF" + $"0000 0000 0000 0000 0000 0400 0210 0110" + $"0090 0050 0030 03F0 0000 0000 0000 0000" + $"000F 000F" +}; + +data 'CURS' (3008, "bottom_side") { + $"0000 0000 0100 0100 0100 0100 0100 1110" + $"0920 0540 0380 0100 0000 7FFC 7FFC 0000" + $"0000 0000 0100 0100 0100 0100 0100 1110" + $"0920 0540 0380 0100 0000 0000 0000 0000" + $"000B 0007" +}; + +data 'CURS' (3009, "bottom_tee") { + $"0000 0000 0000 0180 0180 0180 0180 0180" + $"0180 0180 7FFE 7FFE 0000 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"000B 0007" +}; + +data 'CURS' (3010, "box_spiral") { + $"FFFE 8000 BFFE A002 AFFA A80A ABEA AA2A" + $"AAAA ABAA A82A AFEA A00A BFFA 8002 FFFE" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0008 0008" +}; + +data 'CURS' (3011, "center_ptr") { + $"0000 0300 0300 0780 0780 0FC0 0FC0 1FE0" + $"1FE0 3330 2310 0300 0300 0300 0300 0000" + $"0300 0780 0780 0FC0 0FC0 1FE0 1FE0 3FF0" + $"3FF0 7FF8 77B8 6798 0780 0780 0780 0780" + $"0001 0006" +}; + +data 'CURS' (3012, "circle") { + $"0000 03C0 0FF0 1FF8 3C3C 381C 700E 700E" + $"700E 700E 381C 3C3C 1FF8 0FF0 03C0 0000" + $"03C0 0FF0 1FF8 3FFC 7FFE 7C3E F81F F81F" + $"F81F F81F 7C3E 7FFE 3FFC 1FF8 0FF0 03C0" + $"0007 0007" +}; + +data 'CURS' (3013, "clock") { + $"1FF8 33CC 6466 4992 4F12 4422 63C6 3FFC" + $"2994 2994 2994 2BD4 6996 781E 7FFE 7FFE" + $"1FF8 3FFC 7FFE 7FFE 7FFE 7FFE 7FFE 3FFC" + $"3FFC 3FFC 3FFC 3FFC 7FFE 7FFE 7FFE 7FFE" + $"0004 0008" +}; + +data 'CURS' (3014, "coffee_mug") { + $"03F8 0C06 1001 1C07 33F9 7001 D001 9001" + $"960D DA55 7A55 36ED 10A1 1001 0802 07FC" + $"03F8 0FFE 1FFF 1FFF 3FFF 7FFF FFFF FFFF" + $"FFFF FFFF 7FFF 3FFF 1FFF 1FFF 0FFE 07FC" + $"0004 0003" +}; + +data 'CURS' (3015, "cross") { + $"0280 0280 0280 0280 0280 0280 FEFE 0000" + $"FEFE 0280 0280 0280 0280 0280 0280 0000" + $"0380 0380 0380 0380 0380 0380 FFFE FFFE" + $"FFFE 0380 0380 0380 0380 0380 0380 0000" + $"0007 0007" +}; + +data 'CURS' (3016, "cross_reverse") { + $"4284 A28A 5294 2AA8 16D0 0AA0 FD7E 0280" + $"FD7E 0AA0 16D0 2AA8 5294 A28A 4284 0000" + $"4384 E38E 739C 3BB8 1FF0 0FE0 FFFE FFFE" + $"FFFE 0FE0 1FF0 3BB8 739C E38E 4384 0000" + $"0007 0007" +}; + +data 'CURS' (3017, "crosshair") { + $"0100 0100 0100 0100 0100 0100 0100 FEFE" + $"0100 0100 0100 0100 0100 0100 0100 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0007 0007" +}; + +data 'CURS' (3018, "diamond_cross") { + $"0280 06C0 0AA0 1290 2288 4284 FEFE 0000" + $"FEFE 4284 2288 1290 0AA0 06C0 0280 0000" + $"0280 06C0 0EE0 1EF0 3EF8 7EFC FEFE 0000" + $"FEFE 7EFC 3EF8 1EF0 0EE0 06C0 0280 0000" + $"0007 0007" +}; + +data 'CURS' (3019, "dot") { + $"0000 0000 0780 1FE0 1FE0 3FF0 3FF0 3FF0" + $"3FF0 1FE0 1FE0 0780 0000 0000 0000 0000" + $"0000 0780 1FE0 3FF0 3FF0 7FF8 7FF8 7FF8" + $"7FF8 3FF0 3FF0 1FE0 0780 0000 0000 0000" + $"0006 0006" +}; + +data 'CURS' (3020, "dotbox") { + $"0000 0000 3FFC 2004 2004 2004 2004 2184" + $"2184 2004 2004 2004 2004 3FFC 0000 0000" + $"0000 0000 3FFC 3FFC 300C 300C 318C 33CC" + $"33CC 318C 300C 300C 3FFC 3FFC 0000 0000" + $"0007 0007" +}; + +data 'CURS' (3021, "double_arrow") { + $"0000 0180 03C0 07E0 0DB0 1998 0180 0180" + $"0180 0180 1998 0DB0 07E0 03C0 0180 0000" + $"0180 03C0 07E0 0FF0 1FF8 3FFC 3BDC 03C0" + $"03C0 3BDC 3FFC 1FF8 0FF0 07E0 03C0 0180" + $"0007 0007" +}; + +data 'CURS' (3022, "draft_large") { + $"0000 0002 000C 003C 00F8 03F8 0FF0 00F0" + $"0160 0260 0440 0840 1000 2000 4000 0000" + $"0003 000F 003E 00FE 03FC 0FFC 3FF8 FFF8" + $"03F0 07F0 0EE0 1CE0 38C0 70C0 E080 4080" + $"0001 000E" +}; + +data 'CURS' (3023, "draft_small") { + $"0000 0002 000C 003C 00F8 03F8 0070 00B0" + $"0120 0220 0400 0800 1000 2000 4000 0000" + $"0003 000F 003E 00FE 03FC 0FFC 3FF8 01F8" + $"03F0 0770 0E60 1C60 3840 7040 E000 4000" + $"0001 000E" +}; + +data 'CURS' (3024, "draped_box") { + $"0000 0000 3FFC 2244 2664 2C34 381C 2184" + $"2184 381C 2C34 2664 2244 3FFC 0000 0000" + $"0000 0000 3FFC 3E7C 3E7C 3C3C 399C 23C4" + $"23C4 399C 3C3C 3E7C 3E7C 3FFC 0000 0000" + $"0007 0007" +}; + +data 'CURS' (3025, "exchange") { + $"0000 47C0 6FE0 7C30 4810 4C00 7E00 0000" + $"0000 00FC 0064 1024 187C 0FEC 07C4 0000" + $"C7C0 EFE0 FFF0 FFF8 FC38 FE10 FF00 FF80" + $"03FE 01FE 10FE 387E 3FFE 1FFE 0FEE 07C6" + $"0007 0007" +}; + +data 'CURS' (3026, "fleur") { + $"0000 0180 03C0 07E0 0180 1188 318C 7FFE" + $"7FFE 318C 1188 0180 07E0 03C0 0180 0000" + $"0180 03C0 07E0 0FF0 17E8 3BDC 7FFE FFFF" + $"FFFF 7FFE 3BDC 17E8 0FF0 07E0 03C0 0180" + $"0007 0007" +}; + +data 'CURS' (3027, "gobbler") { + $"0000 0078 0070 4036 4FB0 7FF0 7E30 7C30" + $"3038 00F0 0FE0 0400 0400 0400 0F00 0000" + $"00FC 00FC E0FF FFFF FFFF FFF8 FFF8 FFF8" + $"FFFC 7FFC 3FF8 1FF0 0E00 1F80 1F80 1F80" + $"0003 000E" +}; + +data 'CURS' (3028, "gumby") { + $"3F00 10C0 C820 EAA0 C820 CBA0 F838 383E" + $"0826 0826 092E 0926 0920 1110 2108 3EF8" + $"3F00 1FC0 CFE0 EFE0 CFE0 CFE0 FFF8 3FFE" + $"0FE6 0FE6 0FEE 0FE6 0FE0 1FF0 3FF8 3EF8" + $"0000 0002" +}; + +data 'CURS' (3029, "hand1") { + $"000C 003C 00F0 01E0 03C0 07E0 0FF0 2FE0" + $"7FF0 5FF0 07E0 07C0 4A00 6200 3400 1800" + $"000C 003C 00F0 01E0 03C0 07E0 0FF0 2FE0" + $"7FF0 7FF0 7FE0 7FC0 7E00 7E00 3C00 1800" + $"0000 000D" +}; + +data 'CURS' (3030, "hand2") { + $"0000 3FC0 4020 3F10 0808 0708 0808 0714" + $"0822 0641 0182 0124 0088 0050 0020 0000" + $"0000 3FC0 7FE0 3FF0 0FF8 07F8 0FF8 07FC" + $"0FFE 07FF 01FE 01FC 00F8 0070 0020 0000" + $"0002 0001" +}; + +data 'CURS' (3031, "heart") { + $"0000 3EF8 638C C106 8002 8002 8002 8002" + $"C006 600C 3018 1830 0C60 06C0 0380 0000" + $"0000 3EF8 7FFC FFFE FFFE FFFE FFFE FFFE" + $"FFFE 7FFC 3FF8 1FF0 0FE0 07C0 0380 0000" + $"0003 0007" +}; + +data 'CURS' (3032, "icon") { + $"FFFF D555 AAAB D555 A00B D005 A00B D005" + $"A00B D005 A00B D005 AAAB D555 AAAB FFFF" + $"FFFF FFFF FFFF FFFF F00F F00F F00F F00F" + $"F00F F00F F00F F00F FFFF FFFF FFFF FFFF" + $"0007 0007" +}; + +data 'CURS' (3033, "iron_cross") { + $"0000 3FFC 1FF8 4FF2 67E6 73CE 799E 7FFE" + $"7FFE 799E 73CE 67E6 4FF2 1FF8 3FFC 0000" + $"7FFE 7FFE FFFF FFFF FFFF FFFF FFFF FFFF" + $"FFFF FFFF FFFF FFFF FFFF FFFF 7FFE 7FFE" + $"0007 0006" +}; + +data 'CURS' (3034, "left_ptr") { + $"0000 0800 0C00 0E00 0F00 0F80 0FC0 0FE0" + $"0FF0 0F80 0D80 08C0 00C0 0060 0060 0000" + $"1800 1C00 1E00 1F00 1F80 1FC0 1FE0 1FF0" + $"1FF8 1FFC 1FC0 1DE0 19E0 10F0 00F0 0070" + $"0001 0004" +}; + +data 'CURS' (3035, "left_side") { + $"0000 6000 6000 6080 6100 6200 6400 6FFC" + $"6400 6200 6100 6080 6000 6000 0000 0000" + $"0000 0000 0000 0080 0100 0200 0400 0FFC" + $"0400 0200 0100 0080 0000 0000 0000 0000" + $"0007 0004" +}; + +data 'CURS' (3036, "left_tee") { + $"0000 0C00 0C00 0C00 0C00 0C00 0C00 0FF8" + $"0FF8 0C00 0C00 0C00 0C00 0C00 0C00 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0007 0004" +}; + +data 'CURS' (3037, "leftbutton") { + $"8002 7FFC 7FFC 4444 4554 4554 4554 4554" + $"4444 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 8002" + $"FFFE FFFE FFFE FFFE FFFE FFFE FFFE FFFE" + $"FFFE FFFE FFFE FFFE FFFE FFFE FFFE FFFE" + $"0004 0003" +}; + +data 'CURS' (3038, "ll_angle") { + $"0000 0000 0000 0C00 0C00 0C00 0C00 0C00" + $"0C00 0C00 0FF8 0FF8 0000 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"000B 0004" +}; + +data 'CURS' (3039, "lr_angle") { + $"0000 0000 0000 0030 0030 0030 0030 0030" + $"0030 0030 1FF0 1FF0 0000 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"000B 000B" +}; + +data 'CURS' (3040, "man") { + $"0380 1EF0 0280 8100 4387 244B 1D70 0540" + $"0440 0280 0440 0920 1290 1450 783C F83F" + $"0380 1FF0 0380 8100 4387 27CB 1FF0 07C0" + $"07C0 0380 07C0 0FE0 1EF0 1C70 783C F83F" + $"0001 0007" +}; + +data 'CURS' (3041, "middlebutton") { + $"8002 7FFC 7FFC 4444 5454 5454 5454 5454" + $"4444 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 8002" + $"FFFE FFFE FFFE FFFE FFFE FFFE FFFE FFFE" + $"FFFE FFFE FFFE FFFE FFFE FFFE FFFE FFFE" + $"0004 0007" +}; + +data 'CURS' (3042, "mouse") { + $"0600 0100 0180 0FF0 1008 17E8 1428 1428" + $"17E8 1008 1008 1008 1008 1008 1008 0FF0" + $"0600 0100 0180 0FF0 1FF8 1FF8 1FF8 1FF8" + $"1FF8 1FF8 1FF8 1FF8 1FF8 1FF8 1FF8 0FF0" + $"0000 0000" +}; + +data 'CURS' (3043, "pencil") { + $"0000 00F0 0088 0108 0190 0270 0220 0440" + $"0440 0880 0880 1100 1E00 1C00 1800 1000" + $"0000 00F0 00F8 01F8 01F0 03F0 03E0 07C0" + $"07C0 0F80 0F80 1F00 1E00 1C00 1800 1000" + $"000F 0003" +}; + +data 'CURS' (3044, "pirate") { + $"03C0 07E0 0FF0 1998 1998 0FF0 07E0 03C0" + $"43C2 43C3 2184 1C38 03C0 0FF1 781F 4002" + $"07E0 0FF0 1FF8 3FFC 3FFC 1FF8 0FF0 47E2" + $"E7E7 E7E7 7FFF 3FFC 1FF9 7FFF FFFF F81F" + $"000A 0007" +}; + +data 'CURS' (3045, "plus") { + $"0000 0000 0000 0180 0180 0180 0180 1FF8" + $"1FF8 0180 0180 0180 0180 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0007 0007" +}; + +data 'CURS' (3046, "question_arrow") { + $"07C0 0FE0 1C70 1830 1C30 0C70 00E0 03C0" + $"0380 0280 0280 0EE0 06C0 0380 0100 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0000 0000 3FF8 1FF0 0FE0 07C0 0380 0100" + $"000E 0007" +}; + +data 'CURS' (3047, "right_ptr") { + $"0000 0010 0030 0070 00F0 01F0 03F0 07F0" + $"0FF0 01F0 01B0 0310 0300 0600 0600 0000" + $"0018 0038 0078 00F8 01F8 03F8 07F8 0FF8" + $"1FF8 3FF8 03F8 07B8 0798 0F08 0F00 0E00" + $"0001 000B" +}; + +data 'CURS' (3048, "right_side") { + $"0000 0000 0006 0006 0106 0086 0046 0026" + $"3FF6 0026 0046 0086 0106 0006 0006 0000" + $"0000 0000 0000 0000 0100 0080 0040 0020" + $"3FF0 0020 0040 0080 0100 0000 0000 0000" + $"0008 000B" +}; + +data 'CURS' (3049, "right_tee") { + $"0000 0030 0030 0030 0030 0030 0030 1FF0" + $"1FF0 0030 0030 0030 0030 0030 0030 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0007 000A" +}; + +data 'CURS' (3050, "rightbutton") { + $"8002 7FFC 7FFC 4444 5544 5544 5544 5544" + $"4444 7FFC 7FFC 7FFC 7FFC 7FFC 7FFC 8002" + $"FFFE FFFE FFFE FFFE FFFE FFFE FFFE FFFE" + $"FFFE FFFE FFFE FFFE FFFE FFFE FFFE FFFE" + $"0004 0003" +}; + +data 'CURS' (3051, "rtl_logo") { + $"0000 7FFE 4022 4022 4022 7FE2 4422 4422" + $"4422 4422 47FE 4402 4402 4402 7FFE 0000" + $"0000 7FFE 7FFE 6076 7FF6 7FF6 7C36 6C36" + $"6C36 6C3E 6FFE 6FFE 6E06 7FFE 7FFE 0000" + $"0007 0007" +}; + +data 'CURS' (3052, "sailboat") { + $"0000 0040 0040 0160 0160 0360 0370 0770" + $"0770 0F78 0F78 1F78 1F7C 3E38 0000 0000" + $"0040 00E0 01E0 03F0 03F0 07F0 07F8 0FF8" + $"0FF8 1FFC 1FFC 3FFC 3FFE 7F7C 7E38 0000" + $"000C 0008" +}; + +data 'CURS' (3053, "sb_down_arrow") { + $"0280 0280 0280 0280 0280 0280 0280 0280" + $"0280 0280 0280 0FE0 07C0 0380 0100 0000" + $"0380 0380 0380 0380 0380 0380 0380 0380" + $"0380 0380 0380 1FF0 0FE0 07C0 0380 0100" + $"000E 0007" +}; + +data 'CURS' (3054, "sb_h_double_arrow") { + $"0000 0000 0000 0000 0810 1818 3FFC 781E" + $"3FFC 1818 0810 0000 0000 0000 0000 0000" + $"0000 0000 0000 0810 1818 381C 7FFE FFFF" + $"7FFE 381C 1818 0810 0000 0000 0000 0000" + $"0007 0007" +}; + +data 'CURS' (3055, "sb_left_arrow") { + $"0000 0000 0000 0000 0800 1800 3FFF 7800" + $"3FFF 1800 0800 0000 0000 0000 0000 0000" + $"0000 0000 0000 0800 1800 3800 7FFF FFFF" + $"7FFF 3800 1800 0800 0000 0000 0000 0000" + $"0007 0001" +}; + +data 'CURS' (3056, "sb_right_arrow") { + $"0000 0000 0000 0000 0000 0010 0018 FFFC" + $"001E FFFC 0018 0010 0000 0000 0000 0000" + $"0000 0000 0000 0000 0010 0018 001C FFFE" + $"FFFF FFFE 001C 0018 0010 0000 0000 0000" + $"0008 000E" +}; + +data 'CURS' (3057, "sb_up_arrow") { + $"0000 0080 01C0 03E0 07F0 0140 0140 0140" + $"0140 0140 0140 0140 0140 0140 0140 0140" + $"0080 01C0 03E0 07F0 0FF8 01C0 01C0 01C0" + $"01C0 01C0 01C0 01C0 01C0 01C0 01C0 01C0" + $"0001 0008" +}; + +data 'CURS' (3058, "sb_v_double_arrow") { + $"0000 0100 0380 07C0 0FE0 0280 0280 0280" + $"0280 0280 0280 0FE0 07C0 0380 0100 0000" + $"0100 0380 07C0 0FE0 1FF0 0380 0380 0380" + $"0380 0380 0380 1FF0 0FE0 07C0 0380 0100" + $"0007 0007" +}; + +data 'CURS' (3059, "shuttle") { + $"0020 0070 00F8 01DE 05DE 09DE 11DE 11DE" + $"11DE 11DE 31DE 71DE FDDE 1888 0078 0030" + $"0020 0070 00F8 01FE 07FE 0FFE 1FFE 1FFE" + $"1FFE 1FFE 3FFE 7FFE FFFE 18F8 0078 0030" + $"0000 000A" +}; + +data 'CURS' (3060, "sizing") { + $"0000 7F80 4000 4000 4000 47E0 4420 4422" + $"4422 0422 07E2 0012 000A 0006 01FE 0000" + $"FFC0 FFC0 FFC0 E000 EFF0 EFF0 EC37 EC37" + $"EC37 EC37 0FF7 0FFF 001F 03FF 03FF 03FF" + $"000E 000E" +}; + +data 'CURS' (3061, "spider") { + $"2010 1020 1020 0840 0840 8787 6798 1FE0" + $"1FE0 6798 8787 0840 0840 1020 1020 2010" + $"7038 3870 3870 1CE0 9FE7 EFDF FFFF 7FF8" + $"7FF8 FFFF EFDF 9FE7 1CE0 3870 3870 7038" + $"0007 0007" +}; + +data 'CURS' (3062, "spraycan") { + $"0018 0040 0D18 1E40 1A18 3F00 2100 3900" + $"2900 3900 2900 3900 3900 2100 2100 3F00" + $"0000 0000 0C00 1E00 1E00 3F00 3F00 3F00" + $"3F00 3F00 3F00 3F00 3F00 3F00 3F00 3F00" + $"0002 0007" +}; + +data 'CURS' (3063, "star") { + $"0100 0280 0280 0280 0440 0440 0440 3938" + $"C006 3838 0920 1290 2448 2828 3018 2008" + $"0100 0380 0380 0380 07C0 07C0 07C0 3FF8" + $"FFFE 3FF8 0FE0 1EF0 3C78 3838 3018 2008" + $"0007 0007" +}; + +data 'CURS' (3064, "target") { + $"0000 0380 0FE0 1C70 3018 600C C106 C286" + $"C106 600C 3018 1C70 0FE0 0380 0000 0000" + $"0000 0380 0FE0 1FF0 3C78 701C E38E E38E" + $"E38E 701C 3C78 1FF0 0FE0 0380 0000 0000" + $"0007 0007" +}; + +data 'CURS' (3065, "tcross") { + $"0100 0100 0100 0100 0100 0100 0100 FFFE" + $"0100 0100 0100 0100 0100 0100 0100 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0007 0007" +}; + +data 'CURS' (3066, "top_left_arrow") { + $"0000 6000 7800 3E00 3F80 1FE0 1E00 0D00" + $"0C80 0440 0420 0010 0008 0004 0000 0000" + $"E000 F800 FE00 7F80 7FE0 3FF8 3FFE 1F80" + $"1FC0 0EE0 0E70 0638 061C 020E 0204 0000" + $"0001 0001" +}; + +data 'CURS' (3067, "top_left_corner") { + $"FFF0 FFF0 C000 C000 CFC0 CC00 CA00 C900" + $"C880 C840 C020 C000 0000 0000 0000 0000" + $"0000 0000 0000 0000 0FC0 0C00 0A00 0900" + $"0880 0840 0020 0000 0000 0000 0000 0000" + $"0000 0000" +}; + +data 'CURS' (3068, "top_right_corner") { + $"0FFF 0FFF 0003 0003 03F3 0033 0053 0093" + $"0113 0213 0403 0003 0000 0000 0000 0000" + $"0000 0000 0000 0000 03F0 0030 0050 0090" + $"0110 0210 0400 0000 0000 0000 0000 0000" + $"0000 000F" +}; + +data 'CURS' (3069, "top_side") { + $"0000 7FFC 7FFC 0000 0100 0380 0540 0920" + $"1110 0100 0100 0100 0100 0100 0000 0000" + $"0000 0000 0000 0000 0100 0380 0540 0920" + $"1110 0100 0100 0100 0100 0100 0000 0000" + $"0004 0007" +}; + +data 'CURS' (3070, "top_tee") { + $"0000 0000 0000 0000 7FFE 7FFE 0180 0180" + $"0180 0180 0180 0180 0180 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0004 0007" +}; + +data 'CURS' (3071, "trek") { + $"0100 0000 0380 07C0 0FE0 0EE0 0FE0 07C0" + $"0380 0100 0BA0 0D60 0920 0820 0820 0000" + $"0000 0380 07C0 0FE0 1FF0 1FF0 1FF0 0FE0" + $"07C0 0BA0 1FF0 1FF0 1FF0 1D70 1C70 0820" + $"0000 0007" +}; + +data 'CURS' (3072, "ul_angle") { + $"0000 0000 0000 0FF8 0FF8 0C00 0C00 0C00" + $"0C00 0C00 0C00 0C00 0000 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0003 0004" +}; + +data 'CURS' (3073, "umbrella") { + $"0000 0890 0228 49A6 27C8 1930 610C 0100" + $"0100 0100 0100 0100 0140 0140 0080 0000" + $"0000 0FF0 1FF8 7FFE 7FFC FFFE FBBE E38E" + $"0380 0380 0380 03C0 03E0 03E0 01C0 0080" + $"0004 0007" +}; + +data 'CURS' (3074, "ur_angle") { + $"0000 0000 0000 0000 1FF0 1FF0 0030 0030" + $"0030 0030 0030 0030 0030 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0004 000B" +}; + +data 'CURS' (3075, "watch") { + $"07E0 07E0 07E0 07E0 0810 1088 1088 108C" + $"138C 1008 1008 0810 07E0 07E0 07E0 07E0" + $"07E0 07E0 07E0 07E0 0FF0 1FF8 1FF8 1FFC" + $"1FFC 1FF8 1FF8 0FF0 07E0 07E0 07E0 07E0" + $"0008 000D" +}; + +data 'CURS' (3076, "xterm") { + $"0C60 0280 0100 0100 0100 0100 0100 0100" + $"0100 0100 0100 0100 0100 0100 0280 0C60" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"000B 0007" +}; + +/* + * The following are color versions of some of the + * cursors defined above. The color cursors will be + * used if the exist in preference to the black & white + * cursors. + */ + +data 'crsr' (3004, "boat", purgeable) { + $"8001 0000 0060 0000 0092 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0100 03C0" + $"8460 FFFF 0018 0020 0040 FFC0 0000 0000" + $"0000 0000 0000 0000 0000 0000 0100 03C0" + $"87E0 FFFF FFF8 FFE0 FFC0 FFC0 0000 0000" + $"0000 0000 0007 000F 0000 0000 0000 0000" + $"0000 0000 8008 0000 0000 0010 0010 0000" + $"0000 0000 0000 0048 0000 0048 0000 0000" + $"0004 0001 0004 0000 0000 0000 0112 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0000 0000 000F 0000 0000 0000 00FF FF00" + $"0000 F000 0F32 25F0 0000 6FFF FFFF FFFF" + $"FFFF 2222 2222 221F F000 2222 2222 21F0" + $"0000 3333 3333 4F00 0000 FFFF FFFF FF00" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0000 0000 0000 0000 0000 0000 0000 0000" + $"0000 0000 0000 0000 0007 0000 FFFF FFFF" + $"FFFF 0001 BBBB BBBB BBBB 0002 EEEE EEEE" + $"EEEE 0003 DDDD DDDD DDDD 0004 CCCC CCCC" + $"CCCC 0005 4444 4444 4444 0006 1111 1111" + $"1111 000F 0000 0000 0000" +}; + +data 'crsr' (3013, "clock") { + $"8001 0000 0060 0000 0092 0000 0000 0000" + $"0000 0000 1FF8 33CC 6466 4992 4F12 4422" + $"63C6 3FFC 2994 2994 2994 2BD4 6996 781E" + $"7FFE 7FFE 1FF8 3FFC 7FFE 7FFE 7FFE 7FFE" + $"7FFE 3FFC 3FFC 3FFC 3FFC 3FFC 7FFE 7FFE" + $"7FFE 7FFE 0004 0008 0000 0000 0000 0000" + $"0000 0000 8008 0000 0000 0010 0010 0000" + $"0000 0000 0000 0048 0000 0048 0000 0000" + $"0004 0001 0004 0000 0000 0000 0112 0000" + $"0000 000F FFFF FFFF F000 00F6 05FF FF50" + $"6F00 0F60 5F00 56F5 06F0 0F00 F021 F30F" + $"00F0 0F00 F6F1 000F 00F0 0F00 5F00 00F5" + $"00F0 0F60 05FF FF50 06F0 00FF FFFF FFFF" + $"FF00 00F0 F001 100F 0F00 00F0 F001 100F" + $"0F00 00F0 F021 120F 0F00 00F0 F01F F10F" + $"0F00 0FF0 F021 120F 0FF0 0FF4 F500 005F" + $"4FF0 0FFF FFFF FFFF FFF0 0FFF FFFF FFFF" + $"FFF0 0000 0000 0000 0007 0000 FFFF FFFF" + $"FFFF 0001 4444 4444 4444 0002 AAAA AAAA" + $"AAAA 0003 EEEE EEEE EEEE 0004 5555 5555" + $"5555 0005 DDDD DDDD DDDD 0006 7777 7777" + $"7777 000F 0000 0000 0000" +}; + +data 'crsr' (3014, "coffee_mug") { + $"8001 0000 0060 0000 0092 0000 0000 0000" + $"0000 0000 03F8 0C06 1001 1C07 33F9 7001" + $"D001 9001 960D DA55 7A55 36ED 10A1 1001" + $"0802 07FC 03F8 0FFE 1FFF 1FFF 3FFF 7FFF" + $"FFFF FFFF FFFF FFFF 7FFF 3FFF 1FFF 1FFF" + $"0FFE 07FC 0004 0003 0000 0000 0000 0000" + $"0000 0000 8008 0000 0000 0010 0010 0000" + $"0000 0000 0000 0048 0000 0048 0000 0000" + $"0004 0001 0004 0000 0000 0000 0112 0000" + $"0000 0000 00FF FFFF F000 0000 FF42 2222" + $"4FF0 000F 4221 1111 224F 000F FF11 1111" + $"1FFF 00FF 24FF FFFF F42F 0F5F 2222 2222" + $"222F F52F 2222 2222 222F F40F 2222 2222" + $"222F F40F 4FF2 2224 FF2F F52F F2F2 2F2F" + $"2F2F 0F5F F2F2 535F 2F2F 00FF 4FF2 F3F4" + $"FF2F 000F 2222 F2F2 222F 000F 4222 2222" + $"224F 0000 F422 2222 24F0 0000 0FFF FFFF" + $"FF00 0000 0000 0000 0006 0000 FFFF FFFF" + $"FFFF 0001 CCCC 9999 6666 0002 CCCC CCCC" + $"FFFF 0003 3333 3333 6666 0004 9999 9999" + $"FFFF 0005 6666 6666 CCCC 000F 0000 0000" + $"0000" +}; + +data 'crsr' (3027, "gobbler") { + $"8001 0000 0060 0000 0092 0000 0000 0000" + $"0000 0000 0000 0078 0070 4036 4FB0 7FF0" + $"7E30 7C30 3038 00F0 0FE0 0400 0400 0400" + $"0F00 0000 00FC 00FC E0FF FFFF FFFF FFF8" + $"FFF8 FFF8 FFFC 7FFC 3FF8 1FF0 0E00 1F80" + $"1F80 1F80 0003 000E 0000 0000 0000 0000" + $"0000 0000 8008 0000 0000 0010 0010 0000" + $"0000 0000 0000 0048 0000 0048 0000 0000" + $"0004 0001 0004 0000 0000 0000 0112 0000" + $"0000 0000 0000 0000 0000 0000 0000 0222" + $"2000 0000 0000 0111 0000 0300 0000 0011" + $"0220 0100 1616 1011 0000 0361 6111 1111" + $"0000 0111 1114 4415 0000 0311 1144 4451" + $"0000 0011 4444 4415 1000 0004 4444 5151" + $"0000 0000 1515 1510 0000 0000 0200 0000" + $"0000 0000 0300 0000 0000 0000 0200 0000" + $"0000 0000 2323 0000 0000 0000 0000 0000" + $"0000 0000 0000 0000 0006 0000 FFFF FFFF" + $"FFFF 0001 CCCC 9999 6666 0002 DDDD 0000" + $"0000 0003 FFFF 6666 3333 0004 CCCC CCCC" + $"CCCC 0005 8888 8888 8888 0006 FFFF CCCC" + $"9999" +}; + +data 'crsr' (3028, "gumby") { + $"8001 0000 0060 0000 0092 0000 0000 0000" + $"0000 0000 3F00 10C0 C820 EAA0 C820 CBA0" + $"F838 383E 0826 0826 092E 0926 0920 1110" + $"2108 3EF8 3F00 1FC0 CFE0 EFE0 CFE0 CFE0" + $"FFF8 3FFE 0FE6 0FE6 0FEE 0FE6 0FE0 1FF0" + $"3FF8 3EF8 0000 0002 0000 0000 0000 0000" + $"0000 0000 8008 0000 0000 0010 0010 0000" + $"0000 0000 0000 0048 0000 0048 0000 0000" + $"0004 0001 0004 0000 0000 0000 0112 0000" + $"0000 00FF FFFF 0000 0000 000F 1212 FF00" + $"0000 FF00 F131 31F0 0000 FFF0 F3F3 F3F0" + $"0000 FF00 F131 31F0 0000 FF00 F2FF F2F0" + $"0000 4FFF F121 21FF F000 00FF F212 12FF" + $"FF40 0000 F121 21F0 0FF0 0000 F212 12F0" + $"0FF0 0000 F12F 21F0 FFF0 0000 F21F 12F0" + $"0FF0 0000 F12F 21F0 0000 000F 121F 121F" + $"0000 00F1 212F 2121 F000 00FF FFF0 FFFF" + $"F000 0000 0000 0000 0005 0000 FFFF FFFF" + $"FFFF 0001 0000 BBBB 0000 0002 CCCC CCCC" + $"CCCC 0003 AAAA AAAA AAAA 0004 4444 4444" + $"4444 000F 0000 0000 0000" +}; + +data 'crsr' (3031, "heart") { + $"8001 0000 0060 0000 0092 0000 0000 0000" + $"0000 0000 0000 3EF8 638C C106 8002 8002" + $"8002 8002 C006 600C 3018 1830 0C60 06C0" + $"0380 0000 0000 3EF8 7FFC FFFE FFFE FFFE" + $"FFFE FFFE FFFE 7FFC 3FF8 1FF0 0FE0 07C0" + $"0380 0000 0003 0007 0000 0000 0000 0000" + $"0000 0000 8004 0000 0000 0010 0010 0000" + $"0000 0000 0000 0048 0000 0048 0000 0000" + $"0002 0001 0002 0000 0000 0000 00D2 0000" + $"0000 0000 0000 0FFC FFC0 3AAB AA70 E99B" + $"999C E665 A65C E999 999C E666 665C E999" + $"999C D666 665C 3599 9970 0D66 65C0 0359" + $"9700 00D6 5C00 0035 7000 000F C000 0000" + $"0000 0000 0000 0000 0003 0000 FFFF FFFF" + $"FFFF 0001 DDDD 0000 0000 0002 FFFF 6666" + $"CCCC 0003 0000 0000 0000" +}; + +data 'crsr' (3042, "mouse", purgeable) { + $"8001 0000 0060 0000 0092 0000 0000 0000" + $"0000 0000 BE00 0100 0180 0FF0 1008 17E8" + $"1428 1428 17E8 1008 1008 1008 1008 1008" + $"1008 0FF0 FE00 0100 0180 0FF0 1FF8 1FF8" + $"1FF8 1FF8 1FF8 1FF8 1FF8 1FF8 1FF8 1FF8" + $"1FF8 0FF0 0001 0007 0000 0000 0000 0000" + $"0000 0000 8008 0000 0000 0010 0010 0000" + $"0000 0000 0000 0048 0000 0048 0000 0000" + $"0004 0001 0004 0000 0000 0000 0112 0000" + $"0000 1379 4AF0 0000 0000 0000 000F 0000" + $"0000 0000 000F F000 0000 0000 FFFF FFFF" + $"0000 000F 2111 1112 F000 000F 3655 5563" + $"F000 000F 3513 1351 F000 000F 3533 3351" + $"F000 000F 3655 5561 F000 000F 3311 1111" + $"F000 000F 3333 3333 F000 000F 3333 3333" + $"F000 000F 2222 2222 F000 000F 8888 8888" + $"F000 000F 7888 8887 F000 0000 FFFF FFFF" + $"0000 0000 0000 0000 000B 0000 FFFF FFFF" + $"FFFF 0001 EEEE EEEE EEEE 0002 CCCC CCCC" + $"CCCC 0003 DDDD DDDD DDDD 0004 4444 4444" + $"4444 0005 2222 2222 2222 0006 5555 5555" + $"5555 0007 AAAA AAAA AAAA 0008 BBBB BBBB" + $"BBBB 0009 7777 7777 7777 000A 1111 1111" + $"1111 000F 0000 0000 0000" +}; + +data 'crsr' (3043, "pencil", purgeable) { + $"8001 0000 0060 0000 0092 0000 0000 0000" + $"0000 0000 0000 00F0 0088 0108 0190 0270" + $"0220 0440 0440 0880 0880 1100 1E00 1C00" + $"1800 1000 0000 00F0 00F8 01F8 01F0 03F0" + $"03E0 07C0 07C0 0F80 0F80 1F00 1E00 1C00" + $"1800 1000 000F 0003 0000 0000 0000 0000" + $"0000 0000 8008 0000 0000 0010 0010 0000" + $"0000 0000 0000 0048 0000 0048 0000 0000" + $"0004 0001 0004 0000 0000 0000 0112 0000" + $"0000 0000 0000 0000 0000 0000 0000 FFFF" + $"0000 0000 0000 F404 F000 0000 000F 4042" + $"F000 0000 000F F42F 0000 0000 00F5 3FFF" + $"0000 0000 00F3 52F0 0000 0000 0F35 1F00" + $"0000 0000 0F53 2F00 0000 0000 F532 F000" + $"0000 0000 F312 F000 0000 000F 352F 0000" + $"0000 000F FFF0 0000 0000 000F FF00 0000" + $"0000 000F F000 0000 0000 000F 0000 0000" + $"0000 0000 0000 0000 0006 0000 FFFF FFFF" + $"FFFF 0001 CCCC CCCC CCCC 0002 8888 8888" + $"8888 0003 FFFF FFFF 0000 0004 DDDD 0000" + $"0000 0005 FFFF 6666 3333 000F 0000 0000" + $"0000" +}; + +data 'crsr' (3059, "shuttle") { + $"8001 0000 0060 0000 0092 0000 0000 0000" + $"0000 0000 0020 0070 00F8 01DE 05DE 09DE" + $"11DE 11DE 11DE 11DE 31DE 71DE FDDE 1888" + $"0078 0030 0020 0070 00F8 01FE 07FE 0FFE" + $"1FFE 1FFE 1FFE 1FFE 3FFE 7FFE FFFE 18F8" + $"0078 0030 0000 000A 0000 0000 0000 0000" + $"0000 0000 8008 0000 0000 0010 0010 0000" + $"0000 0000 0000 0048 0000 0048 0000 0000" + $"0004 0001 0004 0000 0000 0000 0112 0000" + $"0000 0000 0000 00F0 0000 0000 0000 0F3F" + $"0000 0000 0000 F343 F000 0000 000F 3404" + $"3FF0 0000 0F4F 3404 3FF0 0000 F55F 3404" + $"3FF0 000F 505F 3404 3FF0 000F 005F 3404" + $"3FF0 000F 005F 3404 3FF0 000F 005F 3404" + $"3FF0 00F3 005F 3404 3FF0 0F33 505F 3404" + $"3FF0 FFF3 3F4F 3404 3FF0 000F F000 1222" + $"1000 0000 0000 0111 1000 0000 0000 0011" + $"0000 0000 0000 0000 0006 0000 FFFF FFFF" + $"FFFF 0001 FFFF 6666 3333 0002 DDDD 0000" + $"0000 0003 4444 4444 4444 0004 8888 8888" + $"8888 0005 DDDD DDDD DDDD 000F 0000 0000" + $"0000" +}; + +data 'crsr' (3062, "spraycan") { + $"8001 0000 0060 0000 0092 0000 0000 0000" + $"0000 0000 0018 0040 0D18 1E40 1A18 3F00" + $"2100 3900 2900 3900 2900 3900 3900 2100" + $"2100 3F00 0000 0000 0C00 1E00 1E00 3F00" + $"3F00 3F00 3F00 3F00 3F00 3F00 3F00 3F00" + $"3F00 3F00 0002 0007 0000 0000 0000 0000" + $"0000 0000 8008 0000 0000 0010 0010 0000" + $"0000 0000 0000 0048 0000 0048 0000 0000" + $"0004 0001 0004 0000 0000 0000 0112 0000" + $"0000 0000 0000 0005 2000 0000 0000 0460" + $"0000 0000 FF1F 6005 2000 000F 33F0 0460" + $"0000 000F 10F0 0005 2000 00FF FFFF 0000" + $"0000 00F8 170F 0000 0000 00F5 F70F 0000" + $"0000 00FA F70F 0000 0000 00F9 F70F 0000" + $"0000 00FA F70F 0000 0000 00F9 F70F 0000" + $"0000 00F5 F70F 0000 0000 00F8 170F 0000" + $"0000 00F8 170F 0000 0000 00FF FFFF 0000" + $"0000 0000 0000 0000 000B 0000 FFFF FFFF" + $"FFFF 0001 AAAA AAAA AAAA 0002 7777 7777" + $"7777 0003 5555 5555 5555 0004 2222 2222" + $"2222 0005 4444 4444 4444 0006 BBBB BBBB" + $"BBBB 0007 DDDD DDDD DDDD 0008 EEEE EEEE" + $"EEEE 0009 6666 6666 CCCC 000A CCCC CCCC" + $"FFFF 000F 0000 0000 0000" +}; + +data 'crsr' (3063, "star") { + $"8001 0000 0060 0000 0092 0000 0000 0000" + $"0000 0000 0100 0280 0280 0280 0440 0440" + $"0440 3938 C006 3838 0920 1290 2448 2828" + $"3018 2008 0100 0380 0380 0380 07C0 07C0" + $"07C0 3FF8 FFFE 3FF8 0FE0 1EF0 3C78 3838" + $"3018 2008 0007 0007 0000 0000 0000 0000" + $"0000 0000 8004 0000 0000 0010 0010 0000" + $"0000 0000 0000 0048 0000 0048 0000 0000" + $"0002 0001 0002 0000 0000 0000 00D2 0000" + $"0000 0003 0000 000D C000 000D C000 000D" + $"C000 0035 7000 0035 7000 0035 7000 0FD7" + $"5FC0 F555 557C 0FD5 5FC0 00D7 5C00 035C" + $"D700 0D70 35C0 0DC0 0DC0 0F00 03C0 0C00" + $"00C0 0000 0000 0000 0002 0000 FFFF FFFF" + $"FFFF 0001 FFFF FFFF 0000 0003 0000 0000" + $"0000" +}; + +data 'crsr' (3071, "trek") { + $"8001 0000 0060 0000 0092 0000 0000 0000" + $"0000 0000 0100 0000 0380 07C0 0FE0 0EE0" + $"0FE0 07C0 0380 0100 0BA0 0D60 0920 0820" + $"0820 0000 0000 0380 07C0 0FE0 1FF0 1FF0" + $"1FF0 0FE0 07C0 0BA0 1FF0 1FF0 1FF0 1D70" + $"1C70 0820 0000 0007 0000 0000 0000 0000" + $"0000 0000 8008 0000 0000 0010 0010 0000" + $"0000 0000 0000 0048 0000 0048 0000 0000" + $"0004 0001 0004 0000 0000 0000 0112 0000" + $"0000 0000 0005 0000 0000 0000 0005 0000" + $"0000 0000 00FF F000 0000 0000 0F31 3F00" + $"0000 0000 F322 23F0 0000 0000 F110 11F0" + $"0000 0000 F311 13F0 0000 0000 0F31 3F00" + $"0000 0000 00FF F000 0000 0000 000F 0000" + $"0000 0000 F0FF F0F0 0000 0000 FF0F 0FF0" + $"0000 0000 400F 0040 0000 0000 4000 0040" + $"0000 0000 4000 0040 0000 0000 0000 0000" + $"0000 0000 0000 0000 0006 0000 FFFF FFFF" + $"FFFF 0001 EEEE EEEE EEEE 0002 9999 9999" + $"FFFF 0003 DDDD DDDD DDDD 0004 3333 3333" + $"6666 0005 DDDD 0000 0000 000F 0000 0000" + $"0000" +}; + +data 'crsr' (3075, "watch", purgeable) { + $"8001 0000 0060 0000 0092 0000 0000 0000" + $"0000 0000 07E0 07E0 07E0 07E0 0810 1088" + $"1088 108C 138C 1008 1008 0810 07E0 07E0" + $"07E0 07E0 07E0 07E0 07E0 07E0 0FF0 1FF8" + $"1FF8 1FF8 1FF8 1FF8 1FF8 0FF0 07E0 07E0" + $"07E0 07E0 0008 000D 0000 0000 0000 0000" + $"0000 0000 8008 0000 0000 0010 0010 0000" + $"0000 0000 0000 0048 0000 0048 0000 0000" + $"0004 0001 0004 0000 0000 0000 0112 0000" + $"0000 0000 0FFF FFF0 0000 0000 0FFF FFF0" + $"0000 0000 0FFF FFF0 0000 0000 0FFF FFF0" + $"0000 0000 F020 202F 0000 000F 0222 F221" + $"F000 000F 2222 F123 F000 000F 0222 F121" + $"FF00 000F 22FF F123 FF00 000F 0222 2221" + $"F000 000F 2222 2213 F000 0000 F131 313F" + $"0000 0000 0FFF FFF0 0000 0000 0FFF FFF0" + $"0000 0000 0FFF FFF0 0000 0000 0FFF FFF0" + $"0000 0000 0000 0000 0004 0000 FFFF FFFF" + $"FFFF 0001 CCCC CCCC CCCC 0002 EEEE EEEE" + $"EEEE 0003 BBBB BBBB BBBB 000F 0000 0000" + $"0000" +}; + diff --git a/macosx/tkMacOSXXStubs.c b/macosx/tkMacOSXXStubs.c new file mode 100644 index 0000000..a92fbcf --- /dev/null +++ b/macosx/tkMacOSXXStubs.c @@ -0,0 +1,862 @@ +/* + * tkMacOSXXStubs.c -- + * + * This file contains most of the X calls called by Tk. Many of + * these calls are just stubs and either don't make sense on the + * Macintosh or thier implamentation just doesn't do anything. Other + * calls will eventually be moved into other files. + * + * Copyright (c) 1995-1997 Sun Microsystems, Inc. + * Copyright 2001, Apple Computer, Inc. + * + * See the file "license.terms" for information on usage and redistribution + * of this file, and for a DISCLAIMER OF ALL WARRANTIES. + * + * RCS: @(#) $Id: tkMacOSXXStubs.c,v 1.2 2002/08/31 06:12:31 das Exp $ + */ + +#include "tkInt.h" +#include <X11/X.h> +#include <X11/Xlib.h> +#include <stdio.h> +#include <stdlib.h> +#include <pthread.h> +#include <sys/types.h> + +#include <X11/Xatom.h> + +#include <Carbon/Carbon.h> +#include "tkMacOSXInt.h" +#include "tkPort.h" +#include "tkMacOSXEvent.h" + +/* + * Because this file is still under major development Debugger statements are + * used through out this file. The define TCL_DEBUG will decide whether + * the debugger statements actually call the debugger or not. + */ + +#ifndef TCL_DEBUG +# define Debugger() +#endif + +#define ROOT_ID 10 + +/* + * Declarations of static variables used in this file. + */ + +static TkDisplay *gMacDisplay = NULL; /* Macintosh display. */ +static char *macScreenName = ":0"; /* Default name of macintosh display. */ + +/* + * Forward declarations of procedures used in this file. + */ + +static XID MacXIdAlloc _ANSI_ARGS_((Display *display)); +static int DefaultErrorHandler _ANSI_ARGS_((Display* display, + XErrorEvent* err_evt)); + +/* + * Other declarations + */ + +int TkMacOSXXDestroyImage _ANSI_ARGS_((XImage *image)); +unsigned long TkMacOSXXGetPixel _ANSI_ARGS_((XImage *image, int x, int y)); +int TkMacOSXXPutPixel _ANSI_ARGS_((XImage *image, int x, int y, + unsigned long pixel)); +XImage *TkMacOSXXSubImage _ANSI_ARGS_((XImage *image, int x, int y, + unsigned int width, unsigned int height)); +int TkMacOSXXAddPixel _ANSI_ARGS_((XImage *image, long value)); +int _XInitImageFuncPtrs _ANSI_ARGS_((XImage *image)); + + +/* + *---------------------------------------------------------------------- + * + * TkpOpenDisplay -- + * + * Create the Display structure and fill it with device + * specific information. + * + * Results: + * Returns a Display structure on success or NULL on failure. + * + * Side effects: + * Allocates a new Display structure. + * + *---------------------------------------------------------------------- + */ + +TkDisplay * +TkpOpenDisplay( + CONST char *display_name) +{ + Display *display; + Screen *screen; + GDHandle graphicsDevice; + int fd = 0; + if (gMacDisplay != NULL) { + if (strcmp(gMacDisplay->display->display_name, display_name) == 0) { + return gMacDisplay; + } else { + return NULL; + } + } + InitCursor(); + + graphicsDevice = GetMainDevice(); + display = (Display *) ckalloc(sizeof(Display)); + display->resource_alloc = MacXIdAlloc; + screen = (Screen *) ckalloc(sizeof(Screen) * 2); + display->default_screen = 0; + display->request = 0; + display->nscreens = 1; + display->screens = screen; + display->display_name = macScreenName; + display->qlen = 0; + display->fd = fd; + + screen->root = ROOT_ID; + screen->display = display; + screen->root_depth = (*(*graphicsDevice)->gdPMap)->cmpSize * + (*(*graphicsDevice)->gdPMap)->cmpCount; + screen->height = (*graphicsDevice)->gdRect.bottom - + (*graphicsDevice)->gdRect.top; + screen->width = (*graphicsDevice)->gdRect.right - + (*graphicsDevice)->gdRect.left; + + screen->mwidth = (screen->width * 254 + 360) / 720; + screen->mheight = (screen->height * 254 + 360) / 720; + screen->black_pixel = 0x00000000; + screen->white_pixel = 0x00FFFFFF; + screen->root_visual = (Visual *) ckalloc(sizeof(Visual)); + screen->root_visual->visualid = 0; + screen->root_visual->class = TrueColor; + screen->root_visual->red_mask = 0x00FF0000; + screen->root_visual->green_mask = 0x0000FF00; + screen->root_visual->blue_mask = 0x000000FF; + screen->root_visual->bits_per_rgb = 24; + screen->root_visual->map_entries = 2 ^ 8; + + gMacDisplay = (TkDisplay *) ckalloc(sizeof(TkDisplay)); + + /* + * This is the quickest way to make sure that all the *Init + * flags get properly initialized + */ + + bzero (gMacDisplay, sizeof (TkDisplay)); + gMacDisplay->display = display; + return gMacDisplay; +} + +/* + *---------------------------------------------------------------------- + * + * TkpCloseDisplay -- + * + * Deallocates a display structure created by TkpOpenDisplay. + * + * Results: + * None. + * + * Side effects: + * Frees memory. + * + *---------------------------------------------------------------------- + */ + +void +TkpCloseDisplay( + TkDisplay *displayPtr) +{ + Display *display = displayPtr->display; + if (gMacDisplay != displayPtr) { + panic("TkpCloseDisplay: tried to call TkpCloseDisplay on bad display"); + } + + /* + * Make sure that the local scrap is transfered to the global + * scrap if needed. + */ + + TkSuspendClipboard(); + + gMacDisplay = NULL; + if (display->screens != (Screen *) NULL) { + if (display->screens->root_visual != (Visual *) NULL) { + ckfree((char *) display->screens->root_visual); + } + ckfree((char *) display->screens); + } + ckfree((char *) display); +} + +/* + *---------------------------------------------------------------------- + * + * MacXIdAlloc -- + * + * This procedure is invoked by Xlib as the resource allocator + * for a display. + * + * Results: + * The return value is an X resource identifier that isn't currently + * in use. + * + * Side effects: + * The identifier is removed from the stack of free identifiers, + * if it was previously on the stack. + * + *---------------------------------------------------------------------- + */ + +static XID +MacXIdAlloc( + Display *display) /* Display for which to allocate. */ +{ + static long int cur_id = 100; + /* + * Some special XIds are reserved + * - this is why we start at 100 + */ + + return ++cur_id; +} + +/* + *---------------------------------------------------------------------- + * + * TkpWindowWasRecentlyDeleted -- + * + * Tries to determine whether the given window was recently deleted. + * Called from the generic code error handler to attempt to deal with + * async BadWindow errors under some circumstances. + * + * Results: + * Always 0, we do not keep this information on the Mac, so we do not + * know whether the window was destroyed. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +int +TkpWindowWasRecentlyDeleted( + Window win, + TkDisplay *dispPtr) +{ + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * DefaultErrorHandler -- + * + * This procedure is the default X error handler. Tk uses it's + * own error handler so this call should never be called. + * + * Results: + * None. + * + * Side effects: + * This function will call panic and exit. + * + *---------------------------------------------------------------------- + */ + +static int +DefaultErrorHandler( + Display* display, + XErrorEvent* err_evt) +{ + /* + * This call should never be called. Tk replaces + * it with its own error handler. + */ + panic("Warning hit bogus error handler!"); + return 0; +} + + +char * +XGetAtomName( + Display * display, + Atom atom) +{ + display->request++; + return NULL; +} + +int +_XInitImageFuncPtrs(XImage *image) +{ + return 0; +} + +XErrorHandler +XSetErrorHandler( + XErrorHandler handler) +{ + return DefaultErrorHandler; +} + +Window +XRootWindow(Display *display, int screen_number) +{ + display->request++; + return ROOT_ID; +} + +XImage * +XGetImage(display, d, x, y, width, height, plane_mask, format) + Display *display; + Drawable d; + int x; + int y; + unsigned int width; + unsigned int height; + unsigned long plane_mask; + int format; +{ + XImage * imagePtr; + Visual * visual = NULL; + int depth = 0; + int offset = 0; + char * data = NULL; + int bitmap_pad = 0; + int bytes_per_line = 0; + CGrafPtr grafPtr; + + imagePtr = XCreateImage(display,visual,depth,format, offset, data, + width, height, bitmap_pad, bytes_per_line ); + grafPtr = TkMacOSXGetDrawablePort(d); + imagePtr->data = (char *) grafPtr; + return imagePtr; +} + +int +XGetGeometry(display, d, root_return, x_return, y_return, width_return, + height_return, border_width_return, depth_return) + Display* display; + Drawable d; + Window* root_return; + int* x_return; + int* y_return; + unsigned int* width_return; + unsigned int* height_return; + unsigned int* border_width_return; + unsigned int* depth_return; +{ + /* Used in tkCanvPs.c & wm code */ + Debugger(); + return 0; +} + +void +XChangeProperty( + Display* display, + Window w, + Atom property, + Atom type, + int format, + int mode, + _Xconst unsigned char* data, + int nelements) +{ + Debugger(); +} + +void +XSelectInput( + Display* display, + Window w, + long event_mask) +{ + Debugger(); +} + +void +XBell( + Display* display, + int percent) +{ + SysBeep(percent); +} + +void +XSetWMNormalHints( + Display* display, + Window w, + XSizeHints* hints) +{ + /* + * Do nothing. Shouldn't even be called. + */ +} + +XSizeHints * +XAllocSizeHints() +{ + /* + * Always return NULL. Tk code checks to see if NULL + * is returned & does nothing if it is. + */ + + return NULL; +} + +XImage * +XCreateImage( + Display* display, + Visual* visual, + unsigned int depth, + int format, + int offset, + char* data, + unsigned int width, + unsigned int height, + int bitmap_pad, + int bytes_per_line) +{ + XImage *ximage; + + display->request++; + ximage = (XImage *) ckalloc(sizeof(XImage)); + + ximage->height = height; + ximage->width = width; + ximage->depth = depth; + ximage->xoffset = offset; + ximage->format = format; + ximage->data = data; + ximage->bitmap_pad = bitmap_pad; + if (bytes_per_line == 0) { + ximage->bytes_per_line = width * 4; /* assuming 32 bits per pixel */ + } else { + ximage->bytes_per_line = bytes_per_line; + } + + if (format == ZPixmap) { + ximage->bits_per_pixel = 32; + ximage->bitmap_unit = 32; + } else { + ximage->bits_per_pixel = 1; + ximage->bitmap_unit = 8; + } + ximage->byte_order = LSBFirst; + ximage->bitmap_bit_order = LSBFirst; + ximage->red_mask = 0x00FF0000; + ximage->green_mask = 0x0000FF00; + ximage->blue_mask = 0x000000FF; + + ximage->f.destroy_image = TkMacOSXXDestroyImage; + ximage->f.get_pixel = TkMacOSXXGetPixel; + ximage->f.put_pixel = TkMacOSXXPutPixel; + ximage->f.sub_image = TkMacOSXXSubImage; + ximage->f.add_pixel = TkMacOSXXAddPixel; + + return ximage; +} + +GContext +XGContextFromGC( + GC gc) +{ + /* TODO - currently a no-op */ + return 0; +} + +Status +XSendEvent( + Display* display, + Window w, + Bool propagate, + long event_mask, + XEvent* event_send) +{ + Debugger(); + return 0; +} + +void +XClearWindow( + Display* display, + Window w) +{ +} + +/* +void +XDrawPoint( + Display* display, + Drawable d, + GC gc, + int x, + int y) +{ +} + +void +XDrawPoints( + Display* display, + Drawable d, + GC gc, + XPoint* points, + int npoints, + int mode) +{ +} +*/ + +void +XWarpPointer( + Display* display, + Window src_w, + Window dest_w, + int src_x, + int src_y, + unsigned int src_width, + unsigned int src_height, + int dest_x, + int dest_y) +{ +} + +void +XQueryColor( + Display* display, + Colormap colormap, + XColor* def_in_out) +{ +} + +void +XQueryColors( + Display* display, + Colormap colormap, + XColor* defs_in_out, + int ncolors) +{ +} + +int +XQueryTree(display, w, root_return, parent_return, children_return, + nchildren_return) + Display* display; + Window w; + Window* root_return; + Window* parent_return; + Window** children_return; + unsigned int* nchildren_return; +{ + return 0; +} + + +int +XGetWindowProperty( + Display *display, + Window w, + Atom property, + long long_offset, + long long_length, + Bool delete, + Atom req_type, + Atom *actual_type_return, + int *actual_format_return, + unsigned long *nitems_return, + unsigned long *bytes_after_return, + unsigned char ** prop_return) +{ + display->request++; + *actual_type_return = None; + *actual_format_return = *bytes_after_return = 0; + *nitems_return = 0; + return 0; +} + +void +XRefreshKeyboardMapping( XMappingEvent* x) +{ + /* used by tkXEvent.c */ + Debugger(); +} + +void +XSetIconName( + Display* display, + Window w, + const char *icon_name) +{ + /* + * This is a no-op, no icon name for Macs. + */ + display->request++; +} + +void +XForceScreenSaver( + Display* display, + int mode) +{ + /* + * This function is just a no-op. It is defined to + * reset the screen saver. However, there is no real + * way to do this on a Mac. Let me know if there is! + */ + display->request++; +} + +void +Tk_FreeXId ( + Display *display, + XID xid) +{ + /* no-op function needed for stubs implementation. */ +} + +/* + *---------------------------------------------------------------------- + * + * TkGetServerInfo -- + * + * Given a window, this procedure returns information about + * the window server for that window. This procedure provides + * the guts of the "winfo server" command. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +TkGetServerInfo( + Tcl_Interp *interp, /* The server information is returned in + * this interpreter's result. */ + Tk_Window tkwin) /* Token for window; this selects a + * particular display and server. */ +{ + char buffer[8 + TCL_INTEGER_SPACE * 2]; + char buffer2[TCL_INTEGER_SPACE]; + + sprintf(buffer, "X%dR%d ", ProtocolVersion(Tk_Display(tkwin)), + ProtocolRevision(Tk_Display(tkwin))); + sprintf(buffer2, " %d", VendorRelease(Tk_Display(tkwin))); + Tcl_AppendResult(interp, buffer, ServerVendor(Tk_Display(tkwin)), + buffer2, (char *) NULL); +} +/* + * Image stuff + */ + +int +TkMacOSXXDestroyImage( + XImage *image) +{ + Debugger(); + return 0; +} + +unsigned long +TkMacOSXXGetPixel( + XImage *image, + int x, + int y) +{ + CGrafPtr grafPtr; + RGBColor cPix; + unsigned long r, g, b, c; + grafPtr = (CGrafPtr)image->data; + SetPort(grafPtr); + GetCPixel(x,y,&cPix); + r = cPix . red; + g = cPix . green; + b = cPix . blue; + c = (r<<16)|(g<<8)|(b); + return c; +} + +int +TkMacOSXXPutPixel( + XImage *image, + int x, + int y, + unsigned long pixel) +{ + CGrafPtr grafPtr; + RGBColor cPix; + unsigned long r, g, b; + grafPtr = (CGrafPtr)image->data; + SetPort(grafPtr); + r = (pixel & image->red_mask)>>16; + g = (pixel & image->green_mask)>>8; + b = (pixel & image->blue_mask); + cPix . red = r; + cPix . green = g; + cPix . blue = b; + SetCPixel(x,y,&cPix); + return 0; +} + +XImage * +TkMacOSXXSubImage( + XImage *image, + int x, + int y, + unsigned int width, + unsigned int height) +{ + Debugger(); + return NULL; +} + +int +TkMacOSXXAddPixel( + XImage *image, + long value) +{ + Debugger(); + return 0; +} + +/* + *---------------------------------------------------------------------- + * + * XChangeWindowAttributes, XSetWindowBackground, + * XSetWindowBackgroundPixmap, XSetWindowBorder, XSetWindowBorderPixmap, + * XSetWindowBorderWidth, XSetWindowColormap + * + * These functions are all no-ops. They all have equivilent + * Tk calls that should always be used instead. + * + * Results: + * None. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +void +XChangeWindowAttributes( + Display* display, + Window w, + unsigned long value_mask, + XSetWindowAttributes* attributes) +{ +} + +void +XSetWindowBackground( + Display *display, + Window window, + unsigned long value) +{ +} + +void +XSetWindowBackgroundPixmap( + Display* display, + Window w, + Pixmap background_pixmap) +{ +} + +void +XSetWindowBorder( + Display* display, + Window w, + unsigned long border_pixel) +{ +} + +void +XSetWindowBorderPixmap( + Display* display, + Window w, + Pixmap border_pixmap) +{ +} + +void +XSetWindowBorderWidth( + Display* display, + Window w, + unsigned int width) +{ +} + +void +XSetWindowColormap( + Display* display, + Window w, + Colormap colormap) +{ + Debugger(); +} + +Status +XStringListToTextProperty( + char** list, + int count, + XTextProperty* text_prop_return) +{ + Debugger(); + return (Status) 0; +} +void +XSetWMClientMachine( + Display* display, + Window w, + XTextProperty* text_prop) +{ + Debugger(); +} +XIC +XCreateIC( + void) +{ + Debugger(); + return (XIC) 0; +} + +/* + *---------------------------------------------------------------------- + * + * TkGetDefaultScreenName -- + * + * Returns the name of the screen that Tk should use during + * initialization. + * + * Results: + * Returns a statically allocated string. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +CONST char * +TkGetDefaultScreenName( + Tcl_Interp *interp, /* Not used. */ + CONST char *screenName) /* If NULL, use default string. */ +{ +#if 0 + if ((screenName == NULL) || (screenName[0] == '\0')) { + screenName = macScreenName; + } + return screenName; +#endif + return macScreenName; +} |